chmod rekursive Erlaubnis für Tausende von Dateien

16

Dies ist eine allgemeinere Frage zum rekursiven "Chmoding".

Ich habe dieses Skript, das irgendwann die Berechtigungen in einem Ordner mit einigen hunderttausend Dateien rekursiv ändern muss. In diesem Ordner werden jeden Tag neue Dateien hinzugefügt, aber die bereits vorhandenen Dateien haben die bereits festgelegten Berechtigungen und ändern sich nicht.

Meine Frage ist ... wenn ich anrufe

chmod 775. -R

Wird versucht, die Berechtigung für die Dateien festzulegen, für die bereits die richtigen Berechtigungen festgelegt wurden, oder nur für die neuen Dateien, für die die richtigen Berechtigungen nicht festgelegt wurden?

Es scheint immer eine Ewigkeit zu dauern, bis dieser Befehl im Skript abgelaufen ist, obwohl es sich bei den "neuen" Dateien nur um einige Tausend handelt und sie ihre Berechtigungen ziemlich schnell ausführen sollten.

Ich habe in der Manpage nach chmod gesucht, aber in diesem Fall scheint nichts erwähnt zu werden.

Wenn chmod nicht vorher nach Berechtigungen sucht, sollte ich dann versuchen, 'find' mit 'chmod' zu kombinieren?

Titi Dumi
quelle
3
Ich frage mich, ob es wirklich langsamer ist, die Berechtigungen zu überprüfen und zu ändern, wenn sie nicht korrekt sind, als sie direkt auf den richtigen Wert zu setzen.
Lgeorget
1
Wenn jemand darüber stolpert und den Befehl find + chmod möchte, ist dies hier: find. ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
Titi Dumi
@lgeorget, Sie sagen also, es ist langsamer, find | chmod zu verwenden? als nur alles zu chmod. (Entschuldigung, habe deinen Kommentar nicht verstanden). Prost
Titi Dumi
Meiner bescheidenen Meinung nach ist es wahrscheinlich langsamer, da es zwei Prozesse starten und die Ausgabe des ersten auf den zweiten umleiten muss, aber ich bin nicht sicher. Dies hängt von der Zeit ab, die erforderlich ist, um Berechtigungen festzulegen, die möglicherweise nicht so wichtig sind, da sie nur 3 Byte lang sind, um sie im Inode zu ändern.
Lgeorget
1
@depquid Das Hauptproblem bei der Leistung ist das Einlesen der Daten in den Festplatten-Cache. Nach dem ersten Durchlauf befindet sich alles im Festplatten-Cache (es sei denn, es ist zu wenig Arbeitsspeicher vorhanden), sodass Sie die Leistung von etwas testen, das in der tatsächlichen Situation nicht der Engpass ist.
Hauke ​​Laging

Antworten:

9

chmodMöglicherweise werden die Berechtigungen von Dateien, die bereits auf die von Ihnen gewünschten Werte festgelegt sind, möglicherweise nicht geändert. Andernfalls müssen sie jedoch überprüft werden, um ihre aktuellen Berechtigungen zu ermitteln [0]. Bei Hunderttausenden von Dateien denke ich nicht, dass es in irgendeiner Weise wichtig wäre. Die Zeit wird höchstwahrscheinlich von den Tools für statjede Datei aufgewendet .

Sie können versuchen find, entweder nach Dateien zu suchen, die neuer als die letzte Ausführung sind, oder nach Dateien, die ausgeführt werden müssen chmod, aber ich glaube nicht, dass Sie eine große Geschwindigkeitsverbesserung erzielen werden.

Wenn es für Ihr Skript möglich ist, können Sie die neuen Dateien möglicherweise zuerst in einem separaten Verzeichnis als "Wartebereich" ablegen. Dann können Sie chmodDIESES Verzeichnis (das nur neue Dateien enthält) und mvdiese mit dem Rest verbinden. Das sollte wesentlich schneller gehen, funktioniert aber leider nicht für jede Anwendung.

[0] Auch wenn versucht wird, die Berechtigung von Dateien festzulegen, die keine Änderungen benötigen, wird das zugrunde liegende Dateisystem wahrscheinlich nichts mit der Anforderung anfangen, da dies nicht erforderlich ist.

mrb
quelle
Dank dafür. Ich werde den Fund versuchen chmod version und sehen, ob es die Dinge schneller macht. Wenn nicht, werde ich versuchen, das Skript so zu ändern, dass ein "Holding" -Ordner wie von Ihnen vorgeschlagen implementiert wird.
Titi Dumi
Der Grund, warum Sie keine Geschwindigkeitsverbesserung erhalten würden, ist, dass der Inode sowohl für die ctime als auch für die Zugriffsrechte gelesen werden muss.
Hauke ​​Laging
10

find / chmod Optimierung

Beides findund chmodmuss lesen

  1. alle Verzeichniseinträge
  2. die Inodes für all diese Einträge

Sie erzielen wahrscheinlich eine Leistungsverbesserung, indem Sie zuerst alle Einträge und dann alle Inodes (auf einer sich drehenden Platte) lesen, da sich dann der Plattenkopf nicht zwischen dem Verzeichnis und den Inodes bewegt. Wie chmod ist dumm (als eine der anderen Antworten erklärt) sollte es durch aufgerufen werden findnur. Aber selbst dann kann es hilfreich sein, alle Inodes zu lesen, bevor die ersten geschrieben werden (vorausgesetzt, Sie haben genügend freien Arbeitsspeicher für den Festplatten-Cache). Ich schlage vor:

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

Die gute Lösung: ACLs

Die gute Lösung kann völlig anders aussehen: Wenn die Dateien in diesem Verzeichnis erstellt (und nicht von einem anderen Ort verschoben) werden, können ACLs die Aufgabe im Handumdrehen erledigen. Sie müssen lediglich die Standard-ACLs für das übergeordnete Verzeichnis festlegen.

Weitere Verbesserungen können durch Dateisystemoptimierungen erreicht werden. Wenn es ext3 / ext4 ist, können Sie e2fsck -Dvon Zeit zu Zeit ausführen . Vielleicht hilft es, dieses Verzeichnis auf ein separates Volume zu legen. Sie können verschiedene Dateisysteme oder Dateisystemeinstellungen ausprobieren (z. B. verschiedene Inode-Größen).

Hauke ​​Laging
quelle
ACLs sind gut, solange Sie nicht an einem NFSv4-Mount arbeiten.
Ostrokach
Die findLösung verdoppelte meine Zeit chmodin einem Hafencontainer.
Nathan GoFundMonica Arthur
8

Angenommen, Sie verwenden chmoddas GNU-Paket coreutils unter Ubuntu 12.10.

chmod 775 . -Rführt den fchmodatSystemaufruf für jede gefundene Datei aus, unabhängig davon, ob die Berechtigungen geändert werden müssen oder nicht. Ich bestätigte dies, indem ich den Code strace chmod 775 . -Rüberprüfte und (Ausschnitt unten) verwendete, um das tatsächliche Verhalten aufzulisten.

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

Die Ausführung fchmodatjeder Datei hat einige Nachteile

  • Der zusätzliche Systemaufruf wird wahrscheinlich erheblich, wenn eine große Anzahl von Dateien geändert wird. Die find/ xargs/ chmodMethode von anderen erwähnt wird wahrscheinlich schneller sein , indem nur Dateien zu ändern , die geändert werden müssen.
  • Der Aufruf zum fchmodatÄndern der Dateistatusänderung (ctime) jeder Datei. Dies führt dazu, dass sich jede Datei / jeder Inode jedes Mal ändert und wahrscheinlich zu einem Überschuss an Schreibzugriffen auf die Festplatte führt. Möglicherweise können Mount-Optionen verwendet werden, um diese überschüssigen Schreibvorgänge zu stoppen.

Ein einfaches Experiment zeigt die zeitlichen Änderungen, die gerade stattfinden 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

Aber das ändert sich nicht für find/ xargs/ chmodein paar Minuten später

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

Ich würde immer dazu neigen , die verwenden find/ xargs/ chmodVersion , da find mehr Kontrolle über die Auswahl Dinge gibt.

Richm
quelle
1

Die [Quelle] (1) zeigt, dass chmod(1)immer versucht wird, den Modus zu setzen und dann mit [fstatat (2)] (2) erneut nachgesehen wird.

Dateien werden über [fts (3)] (3) verarbeitet, das zuvor alle durchsuchten Dateisystemobjekte 'statisieren' muss, um seinen Datenbaum zu erstellen.

Unixlore enthält einen [netten Artikel] (4), in dem chmod(1)gegen einen find/ xargs-Ansatz getimt wird : Letzterer gewinnt um Größenordnungen.

Hier die Kommandozeile angepasst an die ursprüngliche Frage:

find . -print0 | xargs -0 chmod 775

Zwei Gründe:

  1. Das Durchlaufen des Dateisystems wird über die Pipe zwischen den beiden Prozessen, die möglicherweise sogar auf verschiedenen Kernen ausgeführt werden, von den Operationen auf den Dateien entkoppelt.

    1. fts(3)Der Vorgang wird minimiert, da xargs(1)der Verzeichnisbaum "geglättet" wird.

Also ja: Du solltest auf jeden Fall find/ verwenden xargs. für eine einfache Lösung.

Andere Optionen:

  • Spielen Sie mit der [umask] (5) und dem Quellcode der Prozesse, die die neuen Dateien schreiben.

  • Wenn Sie Linux verwenden, hat Ihr System möglicherweise das inotifyKernel-Subsystem aktiviert . In diesem Fall können Sie über [inotifywait (1)] (6) ein Skript für eine effiziente Lösung erstellen.


Anmerkung: Sofern Sie keine Ausführungsberechtigungen für Ihre Dateien wünschen, würde ich vorschlagen, den Aufruf folgendermaßen zu ändern:

find . -type f -print0 | xargs -0 chmod 664
find . -type d -print0 | xargs -0 chmod 775

Hinweis an die Redaktion: Es ist mir nicht gestattet, mehr als zwei Links zum Beitrag hinzuzufügen oder andere Beiträge zu kommentieren. Ich lasse die URLs hier und hoffe, dass ein aufgeschlossener Benutzer mit ausreichendem Ruf sie wieder in den Text einfügt und diesen Absatz löscht.


Kommentar zum Priming des Festplattencaches mit find . -printf "":

Dies kann die Ausführung der folgenden chmodVorgänge beschleunigen , hängt jedoch vom verfügbaren Speicher und der E / A-Last ab. So könnte es funktionieren oder nicht. Das Entkoppeln von traversal ( find) und chmodoperation ermöglicht bereits das Zwischenspeichern, sodass das Vorbereiten des Cache möglicherweise überflüssig ist.

  1. https://lingrok.org/xref/coreutils/src/chmod.c # process_file
  2. https://linux.die.net/man/2/fstatat
  3. https://linux.die.net/man/3/fts
  4. http + www.unixlore.net/articles/speeding-up-bulk-file-operations.html
  5. https://en.wikipedia.org/wiki/Umask
  6. https://linux.die.net/man/1/inotifywait
Georg Lehner
quelle
0

Haben Sie darüber nachgedacht, die Prozesse, mit denen die Datei erstellt wird, so zu ändern, dass sie im 0775-Modus erstellt werden? Schauen Sie sich den umask-Wert in der Umgebung an - 0002 könnte helfen.

D McKeon
quelle