繁体   English   中英

当我的 shell 使用该目录时,为什么可以删除该目录?

[英]Why can a directory be removed when my shell is using that directory?

我不知道我遇到的是错误还是预期的行为,但幸运的是我很快就知道发生了什么。

我将 shell cd 放在 git repo 的子目录中,并且我执行了git rebase -i squash 操作,其中涉及的提交包括创建此目录。

在该操作顺利完成后,shell 处于孤立状态,其中git status (既不在 zsh 主题助手 RPROMPT 中,也不在运行时)表明我什至不在 git 存储库中了。

一旦我运行cd ..一切都很好,一切都有意义。 在变基操作的过程中,Git 已经rm 'd 了我所在的目录(在变基的第一步),然后将其放回原处。 既然它被放回去了,我也可以一步运行cd $(pwd)去那里。

这是一些令人困惑的行为。 虽然,尚不清楚 git 在技术上做错了什么。 我的问题是这会是git的错误还是应该期望用户知道如何处理这种情况?

此外,更广泛的实际根问题是:如果我在已挂载的目录上有一个 shell,为什么不允许删除我的 shell 所在的目录,而不允许弹出磁盘? 这对我来说似乎不一致。

举个例子: fuser <directory>显示当前目录的使用。 如果一个程序“在”一个目录上,它就是“使用”它。

1号航站楼:

$ cd tmp/
$ mkdir test
$ cd test

2 号航站楼:

$ rmdir tmp/test 

1号航站楼:

$ ls 
sh: 0: getcwd() failed: No such file or directory

不一致,是的。 但允许。

附注。 这与git无关。

回答你的第一个问题:

这不是错误,它是 Unix 系统(包括 Linux)一直以来的工作方式。

POSIX 规范中甚至还有一些不错的文字:

[EBUSY] 要删除的目录当前正在被系统或某个进程使用,并且实现认为这是一个错误。

即,某些实现(例如 Windows...)可以将其称为错误,但大多数实现。 即 Unix 变体,不要。

在文件系统中实现的方式是让进程持有对代表目录的对象的引用。 保存此类引用的另一件事是父目录。 git rebase删除了后一个引用,但前一个引用仍然存在。 即使重新创建目录,它也是一个新的文件系统对象,而您的 shell 持有对旧对象的引用。

这就是为什么cd ..cd $(pwd)仍然有效 - 它们重新查找目录并获取新引用,然后释放旧引用。

在旧引用被释放之前,旧对象不会被正式清除。 这意味着在进程释放旧的工作目录之前,目录的元数据不会从磁盘中删除。

回答你的第二个问题:

为了弹出驱动器,您必须卸载挂载点,如上所述,您使用fuser找到的进程持有对该挂载点的引用。

与目录引用一样,在删除对它的所有引用之前,无法清除数量点。 这就是您无法弹出具有引用的驱动器的原因。

一致的做法是允许从目录树中分离文件系统而不实际清理。 您仍然无法弹出驱动器,但至少您可以随意使用目录树。

嗯,这实际上可以用umount --lazy来完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM