[英]Getting "No such file or directory" error when using shell script even though directory successfully moved to target
[英]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.