Permissions

chmod 對數千個文件的遞歸權限

  • March 11, 2022

這是一個關於遞歸“chmoding”的更一般的問題。

我有這個腳本,它在某些時候需要在一個包含幾十萬個文件的文件夾中遞歸地更改權限。每天都會在該文件夾中添加新文件,但是已經存在的文件已經設置了權限並且它們不會更改。

我的問題是……當我打電話時

修改 775 。-R

它會嘗試為已經設置了正確權限的文件設置權限,還是只為沒有正確權限的新文件設置權限?

在腳本中通過這個命令似乎總是需要很長時間,即使“新”文件只有幾千個並且它應該很快地完成它們的權限。

我已經查看了 chmod 的手冊頁,但它似乎沒有提到任何關於這種情況的內容。

如果 chmod 沒有事先檢查權限,我應該開始考慮將 ‘find’ 與 ‘chmod’ 結合起來嗎?

find / chmod 優化

兩者findchmod必須閱讀

  1. 所有目錄條目
  2. 所有這些條目的 inode

通過首先讀取所有條目然後讀取所有 inode(在旋轉磁碟上),您可能會獲得性能改進,因為這樣磁碟頭不會在目錄和 inode 之間移動)。正如愚蠢chmod 那樣(正如其他答案之一所解釋的那樣),它應該find只被呼叫。但即便如此,在寫入第一個 inode 之前讀取所有 inode 可能會有所幫助(假設您有足夠的空閒 RAM 用於磁碟記憶體)。我建議這樣做:

find . -printf "" # reading the file names only
find . ! -perm 775 -printf "" # reading all the inodes (file names are cached)
find . ! -perm 775 -exec chmod 775 + # writing to the cache without reading from disk

好的解決方案:ACL

好的解決方案可能完全不同:如果文件是在這個目錄中創建的(而不是從其他地方移動),那麼 ACL 可以即時完成這項工作。您只需在父目錄上設置預設 ACL。

通過文件系統優化可以實現進一步的改進。如果是 ext3/ext4,那麼您可能會e2fsck -D不時執行。也許將這個目錄放到一個單獨的捲上會有所幫助。您可以嘗試不同的文件系統或文件系統設置(例如不同的 inode 大小)。

假設在 Ubuntu 12.10 上chmod使用GNU coreutils 包。

chmod 775 . -R對找到的每個文件執行fchmodat系統呼叫,而不管權限是否需要更改。我通過檢查程式碼和使用strace chmod 775 . -R(下面的片段)列出實際行為來確認這一點。

newfstatat(4, "d", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "d", 0775)                  = 0
newfstatat(4, "c", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "c", 0775)                  = 0
newfstatat(4, "a", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "a", 0775)                  = 0
newfstatat(4, "b", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "b", 0775)                  = 0

fchmodat在每個文件上執行有幾個缺點

  • 如果大量文件被更改,額外的系統呼叫可能會變得很重要。find//別人提到的方法可能會更快,只更改需要更改的文件xargschmod
  • 呼叫fchmodat更改每個文件的文件狀態修改(ctime)。這將導致每個文件/inode 每次都更改,並可能導致磁碟寫入過多。可以使用掛載選項來停止這些多餘的寫入。

一個簡單的實驗顯示了直接發生的 ctime 變化chmod

auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 d
auser@duncow:/tmp/blah.test$ chmod 775 . -R
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d

但這並沒有改變find//xargs幾分鐘chmod

auser@duncow:/tmp/blah.test$ date
Tue Jun 18 18:27:27 BST 2013
auser@duncow:/tmp/blah.test$ find . ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d

我總是傾向於使用find//版本xargschmod因為 find 可以更好地控制選擇內容。

引用自:https://unix.stackexchange.com/questions/79868