chmod autorisation récursive sur des milliers de fichiers

16

Il s'agit d'une question plus générale sur le «chmoding» récursif.

J'ai ce script qui à un moment donné doit changer les autorisations récursivement dans un dossier qui contient quelques centaines de milliers de fichiers. De nouveaux fichiers sont ajoutés chaque jour dans ce dossier, mais ceux qui s'y trouvent déjà ont les autorisations déjà définies et ne changent pas.

Ma question est ... quand j'appelle

chmod 775. -R

essaie-t-il de définir l'autorisation pour les fichiers qui ont déjà les bonnes autorisations définies, ou uniquement pour les nouveaux fichiers qui n'ont pas les bonnes autorisations?

Il semble que cela prenne toujours du temps pour dépasser cette commande dans le script, même si les «nouveaux» fichiers ne sont que quelques milliers et que cela devrait faire assez rapidement leurs autorisations.

J'ai regardé la page de manuel de chmod, mais elle ne semble rien mentionner sur ce cas.

Si chmod ne vérifie pas les autorisations au préalable, dois-je commencer à chercher à combiner 'find' avec 'chmod'?

Titi Dumi
la source
3
Je me demande s'il est vraiment plus lent de vérifier les autorisations et de les modifier si elles ne sont pas correctes que de les définir directement sur la valeur correcte.
lgeorget
1
si quelqu'un bute dessus et veut la commande find + chmod, la voici: find. ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
Titi Dumi
@lgeorget, donc vous dites qu'il est plus lent d'utiliser find | chmod? que de tout chmoder. (désolé, je n'ai pas compris votre commentaire). cheers
Titi Dumi
À mon humble avis, c'est probablement plus lent car il doit lancer deux processus et rediriger la sortie du premier vers le second mais je ne suis pas sûr. Cela dépend du temps nécessaire pour définir des autorisations qui ne sont peut-être pas si importantes car elles ne sont que de 3 octets à modifier dans l'inode.
lgeorget
1
@depquid Le principal problème de performances ici est la lecture des données dans le cache disque. Après la première exécution, tout est dans le cache disque (sauf s'il y a trop peu de mémoire), vous testez donc les performances de quelque chose qui n'est pas le goulot d'étranglement dans la situation réelle.
Hauke ​​Laging

Réponses:

9

chmodpeut ou peut ne pas modifier les autorisations des fichiers qui sont déjà définis sur ce que vous voulez, mais sinon, il devra toujours les vérifier pour voir quelles sont leurs autorisations actuelles [0]. Avec des centaines de milliers de fichiers, je ne pense pas que cela importerait de toute façon; le temps est très probablement consacré aux outils de statchaque fichier.

Vous pouvez essayer d'utiliser findpour rechercher des fichiers plus récents que la dernière exécution ou des fichiers qui doivent chmodêtre exécutés, mais je ne pense pas que vous obtiendrez beaucoup d'amélioration de la vitesse.

Si possible pour votre script, vous pourrez peut-être d'abord placer les nouveaux fichiers dans un répertoire séparé, en tant que zone "d'attente". Ensuite, vous pouvez chmodQUE le répertoire (qui n'a que de nouveaux fichiers), et mvles avec le reste. Cela devrait être sensiblement plus rapide, mais ne fonctionnera malheureusement pas pour toutes les applications.

[0] Même s'il essaie de définir l'autorisation des fichiers qui ne nécessitent aucune modification, le système de fichiers sous-jacent ne fera probablement rien avec la demande, car elle n'est pas nécessaire.

mrb
la source
Merci pour ça. Je vais essayer la trouvaille | version chmod et voyez si cela accélère les choses. Sinon, j'essaierai de modifier le script pour implémenter un dossier «d'attente» comme vous l'avez suggéré.
Titi Dumi
La raison pour laquelle vous n'obtiendrez pas d'amélioration de la vitesse est que l'inode doit être lu à la fois pour le ctime et les droits d'accès.
Hauke ​​Laging
10

optimisation find / chmod

Les deux findet chmoddoivent lire

  1. toutes les entrées du répertoire
  2. les inodes pour toutes ces entrées

Vous obtenez probablement une amélioration des performances en lisant d'abord toutes les entrées, puis tous les inodes (sur un disque rotatif) car la tête de disque ne se déplace pas entre le répertoire et les inodes). Comme chmod c'est stupide (comme l'explique l'une des autres réponses), il ne devrait être appelé findque par le biais . Mais même alors, il peut être utile de lire tous les inodes avant que le premier ne soit écrit (en supposant que vous avez suffisamment de RAM libre pour le cache disque). Je suggère ceci:

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

La bonne solution: les ACL

La bonne solution peut être complètement différente: si les fichiers sont créés dans ce répertoire (et ne sont pas déplacés ailleurs), les ACL peuvent faire le travail à la volée. Il vous suffit de définir les ACL par défaut sur le répertoire parent.

D'autres améliorations peuvent être obtenues grâce aux optimisations du système de fichiers. S'il s'agit de ext3 / ext4, vous pouvez exécuter e2fsck -Dde temps en temps. Peut-être que cela aide de mettre ce répertoire sur un volume séparé. Vous pouvez essayer différents systèmes de fichiers ou paramètres de système de fichiers (par exemple, différentes tailles d'inode).

Hauke ​​Laging
la source
Les ACL sont bonnes tant que vous ne travaillez pas sur un montage NFSv4.
ostrokach
La findsolution a doublé mon temps, à l' chmodintérieur d'un conteneur docker.
Nathan ReinstateMonica Arthur
8

En supposant l'utilisation de chmoddu paquet GNU coreutils sur Ubuntu 12.10.

chmod 775 . -Rexécute l' fchmodatappel système pour chaque fichier qu'il trouve, que les autorisations doivent ou non être modifiées. J'ai confirmé cela en inspectant le code et en utilisant strace chmod 775 . -R(extrait ci-dessous) pour répertorier le comportement réel.

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

Il y a quelques inconvénients à s'exécuter fchmodatsur chaque fichier

  • L'appel système supplémentaire deviendra probablement important si un grand nombre de fichiers sont modifiés. La méthode find/ xargs/ chmodmentionnée par d'autres sera probablement plus rapide en ne modifiant que les fichiers qui doivent être modifiés.
  • L'appel à fchmodatchange la modification de l'état du fichier (ctime) de chaque fichier. Cela entraînera la modification de chaque fichier / inode à chaque fois et entraînera probablement un nombre excessif d'écritures sur disque. Il peut être possible d'utiliser des options de montage pour arrêter ces écritures excessives.

Une expérience simple montre les changements de temps qui se produisent pour les droites 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

Mais cela ne change pas pendant find/ xargs/ chmodquelques minutes plus tard

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

J'aurais toujours tendance à utiliser la version find/ xargs/ chmodparce que find donne plus de contrôle sur la sélection des choses.

Richm
la source
1

La [source] (1) montre, qui chmod(1)essaie toujours de définir le mode, puis vérifie à nouveau avec [fstatat (2)] (2).

Les fichiers sont traités via [fts (3)] (3), qui doit au préalable «stat» tous les objets du système de fichiers traversé pour construire son arbre de données.

Unixlore propose un [bel article] (4) où chmod(1)est chronométré par rapport à une approche find/ xargs: cette dernière gagne en magnitudes.

Voici la ligne de commande adaptée à la question d'origine:

find . -print0 | xargs -0 chmod 775

Deux raisons:

  1. La traversée du système de fichiers est découplée des opérations sur les fichiers via le canal entre les deux processus, qui peuvent même s'exécuter sur des cœurs différents.

    1. fts(3)l'opération est minimisée, car xargs(1)«aplatit» l'arborescence des répertoires.

Alors oui: vous devez absolument utiliser find/ xargs. pour une solution simple.

Autres options:

  • Jouez avec le [umask] (5) et le code source du ou des processus d'écriture des nouveaux fichiers.

  • Si vous utilisez Linux, il est probable que votre système ait activé le inotifysous-système du noyau. Dans ce cas, vous pouvez écrire une solution efficace via [inotifywait (1)] (6).


Sidenote: à moins que vous ne souhaitiez exécuter des autorisations sur vos fichiers, je suggère de modifier l'invocation comme suit:

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

Note aux rédacteurs: je ne suis pas autorisé à ajouter plus de deux liens à l'article, ni à commenter d'autres articles. Je laisse les URL ici et j'espère qu'un utilisateur au cœur ouvert avec une réputation suffisante les remettra dans le texte et supprimera ce paragraphe.


Commentez sur l' amorçage du cache disque avec find . -printf "":

Cela peut accélérer l'exécution des chmodopérations suivantes , mais dépend de la mémoire disponible et de la charge d'E / S. Cela pourrait donc fonctionner ou non. Le découplage de traversal ( find) et de l' chmodopération prévoit déjà la mise en cache, donc l'amorçage du cache peut être superflu.

  1. https + lingrok.org / xref / coreutils / src / chmod.c # fichier_processus
  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
la source
0

Avez-vous envisagé de modifier le ou les processus qui créent le fichier pour les créer avec le mode 0775? Regardez la valeur umask dans l'environnement - 0002 peut vous aider.

D McKeon
la source