
在以下情況下ls -alh
total 0
drwxrwx--- 1 user http 20 Nov 30 08:08 .
drwxrws--- 1 user http 310 Nov 30 08:07 ..
drwx------ 1 http http 10 Nov 30 08:08 empty-subdir
drwx------ 1 http http 12 Nov 30 08:08 non-empty-subdir
其中存在兩個子目錄(不屬於我),我將其列出為:
sudo ls empty-subdir -alh
total 0
drwx------ 1 http http 10 Nov 30 08:08 .
drwxrwx--- 1 user http 20 Nov 30 08:08 ..
sudo ls non-empty-subdir -alh
total 0
drwx------ 1 http http 12 Nov 30 08:08 .
drwxrwx--- 1 user http 20 Nov 30 08:08 ..
drwx------ 1 http http 0 Nov 30 08:08 subdir
兩個子目錄之間的差異在於非空子目錄non-empty-subdir
包含一個資料夾。
我的問題是,嘗試rm -rf
刪除子目錄是否是故意的,我得到的結果是:
$ rm empty-subdir -rf
$ rm non-empty-subdir -rf
rm: cannot remove 'non-empty-subdir': Permission denied
$ ls -alh
total 0
drwxrwx---+ 1 user http 10 Nov 30 08:14 .
drwxrws---+ 1 user http 310 Nov 30 08:07 ..
drwx------+ 1 http http 12 Nov 30 08:08 non-empty-subdir
似乎允許對目錄具有寫入權限的使用者刪除檔案的條目或其他使用者的空子目錄,但不允許刪除檔案的條目。非空子目錄。
這個問題的理想答案將提供以下資訊:
- 確認所概述的行為可以在其他機器上重現(而不僅僅是我搞砸的盒子的怪癖)
- 解釋該行為的基本原理(例如是否有用例?)
- 系統(BSD、Linux...)之間是否有差異的概述
更新:關於 Ipor Sircer 的評論,我確實重新測試了該場景,沒有任何 ACL 功能,結果是一樣的。因此,我修改了問題,+
從清單中刪除 es,以免產生該行為可能與 ACL 相關的想法。
答案1
rmdir()
僅當目錄為空時才可以刪除該目錄(透過系統呼叫)。
rm -r dir
刪除目錄及其中的所有文件,從目錄樹的葉子開始,一直向上到根 ( dir
)。
要刪除檔案(對於rmdir()
目錄和unlink()
其他類型的檔案或*at()
變體),重要的不是檔案本身的權限,而是要從中刪除檔案的目錄的權限(注意t
權限中的位,例如對於/tmp
,增加了進一步的複雜性)。
首先,您並沒有真正刪除文件,您正在取消它與目錄的連結(當它是您要刪除的最後一個連結時,檔案最終會被刪除),也就是說,您正在修改目錄,因此您需要修改對該目錄的(寫入)權限。
您無法刪除的原因non-empty-dir
是您無法subdir
先取消鏈接,因為您無權修改non-empty-dir
.您有權取消non-empty-dir
與主目錄的鏈接,因為您對該主目錄具有寫入/修改權限,只是您無法刪除不為空的目錄。
在您的情況下,正如 @PeterCordes 在註釋中指出的那樣,rmdir()
系統呼叫失敗並顯示ENOTEMPTY
(Directory notempty) 錯誤代碼,但因為您沒有讀目錄的權限,rm
甚至無法找出subdir
需要取消鏈接的文件和目錄(包括 )才能清空它(並不是說它知道就可以取消鏈接,因為它沒有寫權限)。
您也可能遇到以下情況rm
可以如果目錄能夠找出其中包含哪些文件,則刪除目錄,就像只寫目錄的情況一樣:
$ mkdir dir
$ touch dir/file
$ chmod a=,u=wx dir
$ ls -ld dir
d-wx------ 2 me me 4096 Nov 30 19:43 dir/
$ rm -rf dir
rm: cannot remove 'dir': Permission denied
儘管如此,我還是能夠刪除它,因為我碰巧知道它只包含一個file
檔案:
$ rm dir/file
$ rmdir dir
$
另請注意,對於現代的 Unices,您可以重命名它non-empty-dir
,但在 Linux 或 FreeBSD(但不是 Solaris)等一些系統上,不是將其移至不同的目錄,即使您也對該目錄具有寫入權限,如(我認為對於Linux,正如建議的那樣相關程式碼的註釋)這樣做將涉及修改non-empty-dir
(..
其中的條目將指向不同的目錄)。
有人可能會說,刪除 yourempty-dir
還涉及刪除其中的..
和.
條目,因此要修改它,但係統仍然允許您這樣做。
答案2
忽略 ACL 帶來的潛在變化,我可以確認我的系統(沒有 ACL)的這種行為。
觀察到的行為是兩個原則的邏輯結果:
1) 目錄的權限決定了誰可以更改目錄,也就是刪除目錄中的條目。該目錄中條目的權限在此不起作用。
2)刪除檔案可能需要刪除和清理相關訊息,即索引節點、區塊分配清單等。變得無法訪問,但相關資訊不會被清除。
因此您可以刪除,因為您empty-subdir
有權寫入它所在的目錄。non-empty-subdir
這確實沒有任何理由或用例。人們可以在核心中建立子目錄的遞歸清理,但是原始的 Unix 使一切變得簡單,並且當可以使用用戶空間實用程式來實現遞歸清理時,它會變得太複雜。
我無法提供不同風格之間的全面概述,但這是原始 Unix 中的行為,我希望它在每個 Unix 風格中都是相同的,如果有 Unix 風格,我會感到驚訝表現不同。
答案3
我嘗試重現您所描述的內容,然後運行strace rm -rf ./nonempty
。揭示的內容如下:
unlinkat(4, "subdir", AT_REMOVEDIR) = -1 EACCES (Permission denied)
並根據unlinkat
手冊(在Linux上與相同unlink(2)
,重點是我添加的):
EACCES 進程的有效 UID 不允許對包含路徑名的目錄進行寫入訪問,或者 路徑名中的目錄之一不允許搜尋權限。 (另請參見 path_resolution(7)。)
由於父目錄nonempty
不授予user
x(搜尋)權限,因此根據無法刪除EACCES
的描述,這是有意義的。subdir