簡體   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