删除目录时出现“ ls”错误


13

我有两个弹壳。第一个位于目录A中。第二个删除目录A,然后重新创建它。当我回到第一个shell并输入时ls,输出为:

ls: cannot open directory .: Stale file handle

为什么?我认为第一个外壳程序(在不存在的目录中保持打开状态的外壳程序)将在等待下一个命令时“冻结”,并且不会“意识到”该目录已被删除并重新创建。除了字符串以外,shell是否对它的当前工作目录保留“更深”的引用$PWD


2
一个没有答案的方法,但是如果您只是希望您的外壳退回它的脚上,则可以运行cd $PWD
dhag 2015年

我想了解发生了什么,我知道很容易取回外壳:)
fonini 2015年

该目录在NFS服务器上吗?我认为这是唯一的获取旧文件句柄的情况。
2015年

该目录是本地目录。当您在系统中执行此操作时,结果是否有所不同?
fonini 2015年

Answers:


17

目录(如任何文件)不是由其名称定义的。将名称视为目录的地址。当您移动目录时,它仍然是同一目录,就像您移动到另一间房子一样,您仍然是同一个人。如果您删除一个目录并用相同的名称创建一个新目录,那么它就是一个新目录,就像搬进您以前居住的房子的人不是您一样。

每个进程都有一个工作目录cd外壳程序中的命令更改了外壳程序的当前工作目录。该pwd命令将“¹”路径打印到当前工作目录。

当您删除目录A时,这样做是为了删除A在其父目录中的条目。目录A本身保留在文件系统中,但处于分离状态,没有名称。尚未删除它,因为某个进程(即第一个shell)正在使用它。当您在第一个外壳中更改目录时,该目录最终被删除。当在进程仍处于打开状态时删除文件时,也会发生同样的事情:文件的目录条目会立即被删除,而文件本身在停止使用时也会被删除。

同样,观察目录移动时会发生什么。

mkdir one two
touch one/1 two/2
cd one
ls

在另一个外壳中:

mv one tmp
mv two one
mv tmp two

在第一个外壳中:

ls

该文件1位于最初调用的目录中,one现在称为two。该文件2位于最初调用的目录中,two现在称为one

¹ 更确切地说,一条路径,如果涉及符号链接或其他细微之处,则可能不是唯一的。


因此,这里的关键点在于,进程拥有其工作目录的索引节点,而不仅仅是路径?
Nacht-恢复莫妮卡2015年

1
@Nacht该进程保存一个描述符,但是内核执行所有映射(描述符/文件表条目/索引节点)。实际上,在内部,内核不存储路径(因为有趣的东西在inode中,而不是路径中)。此外,“路径”仅是指向文件的一个链接...可能有多个:)
约翰·史密斯

哦,对了,它拥有一个描述符。所以bash总是持有工作目录的fd?当然不是所有进程都有工作目录的fds ...我想我还记得fds在stdin / out / err之后从值3开始
Nacht-恢复Monica 2015年

2
@Nacht当前目录不是文件描述符,但是它的工作原理很像一个文件描述符。内核会在每个进程中维护它。在Linux上,您可以在中看到它/proc/<pid>/cwd,其工作方式类似于/proc/<pid>/fd/<number>。这是CWD在输出lsof
吉尔(Gilles)'所以

cd - && cd -在这种情况下可以自动进行?
Vitaly Zdanevich '16

8

新目录A与目录A不同。可以stat在删除旧目录之前和在创建新目录之后使用命令检查该目录,您将看到不同的索引节点号。
我认为这与内核的工作方式有关。它只是跟踪每个进程的当前目录的i编号。因此,由于存在不同的i数,这将导致不同的碰撞。


应该注意的是,一个索引节点是一个结构,而不是唯一的数字。可以唯一标识它,但是它包含比其ID更多的信息。这就是使它比链接更重要的原因。
约翰·史密斯

1
@JohnWHSmith我将删除此答案,因为Gilles更好。
taliezin

6
那没有理由删除您的!如果您有这种感觉,您可以在回答中添加一个免责声明,说明您认为另一个更好。
terdon

7

这是预期的行为。新目录A与旧目录A不同,只是名称相同。因此,第一个航站楼的$ PWD仍然不见了,当您执行时,它并没有神奇地重新出现mkdir A


2
您能否详细说明“新目录A与旧目录A不同”。文件/目录的哪些方面发生了变化?它和inode号有关吗?很抱歉问,但是我只是在学习这个。
rahul 2015年

2
@rahul从哲学上讲,其身份发生了变化-在相同位置没有任何内容的情况下创建了一个新目录。在实现级别,是的,所有打开的文件都由inode标识,并且旧目录和新目录将具有具有不同inode编号的不同inode。
霍布斯

0

目录(如文件)具有与之关联的索引节点:

307%mkdir ABC

308%ls -i 11997708 A 11997709 B 11997710 C

索引节点是一种数据结构,其中包含有关目录或文件的信息。每个目录和文件都有一个。将其视为地址(实际上是索引号)。

如果我在A中,索引节点号为11997708,并且在另一个外壳中(或将在相同的外壳中),则删除目录A,然后重新创建它并使索引节点ls:

309%CD A

均方根值310%../A

311%mkdir ../A

312%ls -i ..

11997720 A 11997709 B 11997710 C

i节点是不同的,因此如果它尝试在已删除的目录A中创建文件:

313%触摸此

touch:无法触摸“ this”:没有此类文件或目录

因为我所在的目录-不再与inode 11997720关联 -所以我当前所在的目录不再具有合法的地址/索引-inode。因此错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.