permiso recursivo de chmod en miles de archivos

16

Esta es una pregunta más general sobre 'chmoding' recursivamente.

Tengo este script que en algún momento necesita cambiar los permisos de forma recursiva en una carpeta que tiene unos cientos de miles de archivos. Todos los días se agregan nuevos archivos a esa carpeta, pero los que ya están allí tienen los permisos ya establecidos y no cambian.

Mi pregunta es ... cuando llamo

chmod 775. -R

¿intenta establecer el permiso para los archivos que ya tienen establecidos los permisos correctos, o solo para los archivos nuevos que no tienen los permisos correctos?

Parece que siempre lleva años superar este comando en el script, a pesar de que los archivos 'nuevos' son solo unos pocos miles y deberían hacer sus permisos con bastante rapidez.

He buscado chmod en la página de manual, pero no parece mencionar nada en este caso.

Si chmod no comprueba los permisos de antemano, ¿debería comenzar a buscar la combinación de 'find' con 'chmod'?

Titi Dumi
fuente
3
Me pregunto si es realmente más lento verificar los permisos y cambiarlos si no son correctos que establecerlos directamente en el valor correcto.
lgeorget
1
si alguien se topa con esto y quiere el comando find + chmod, aquí está: find. ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
Titi Dumi
@lgeorget, ¿está diciendo que es más lento usar find | chmod? que simplemente cambiar todo. (lo siento, no entendí por tu comentario). salud
Titi Dumi
En mi humilde opinión, probablemente sea más lento, ya que necesita lanzar dos procesos y redirigir la salida del primero al segundo, pero no estoy seguro. Depende del tiempo que lleve establecer los permisos, lo que puede no ser tan importante ya que solo tienen 3 bytes para modificar en el inodo.
lgeorget
1
@depquid El principal problema de rendimiento aquí es leer los datos en el caché del disco. Después de la primera ejecución, todo está en la memoria caché del disco (a menos que haya muy poca memoria), por lo que está probando el rendimiento de algo que no es el cuello de botella en la situación real.
Hauke ​​Laging

Respuestas:

9

chmodpodría o no cambiar los permisos de los archivos que ya están configurados a lo que desea, pero si no, aún tendría que verificarlos para ver cuáles son sus permisos actuales [0]. Con cientos de miles de archivos, no creo que importe de ninguna manera; Es muy probable que las herramientas statempleen el tiempo en cada archivo.

Puede intentar usar findpara buscar archivos más nuevos que la última ejecución o los archivos que deben chmodejecutarse, pero no creo que vaya a mejorar mucho la velocidad.

Si es posible para su secuencia de comandos, es posible que primero pueda colocar los nuevos archivos en un directorio separado, como un área de "retención". Luego puede chmodESO directorio (que solo tiene archivos nuevos) y mvagregarlos al resto. Eso debería ser sustancialmente más rápido, pero desafortunadamente no funcionará para todas las aplicaciones.

[0] Incluso si intenta establecer el permiso de los archivos que no necesitan ningún cambio, el sistema de archivos subyacente probablemente no hará nada con la solicitud, porque es innecesario.

mrb
fuente
Gracias por eso. Probaré el hallazgo | versión chmod y ver si hace las cosas más rápido. Si no, trataré de modificar el script para implementar una carpeta de 'retención' como usted sugirió.
Titi Dumi
La razón por la que no obtendría una mejora de velocidad es que el inodo debe leerse tanto para ctime como para los derechos de acceso.
Hauke ​​Laging
10

encontrar / optimización chmod

Ambos findy chmodtengo que leer

  1. todas las entradas de directorio
  2. los inodes para todas estas entradas

Probablemente obtenga una mejora en el rendimiento al leer primero todas las entradas y luego todos los inodes (en un disco giratorio) porque el cabezal del disco no se mueve entre el directorio y los inodes). Como chmod es estúpido (como explica una de las otras respuestas), solo se debe llamar find. Pero incluso entonces, puede ser útil leer todos los inodos antes de que se escriba el primero (suponiendo que tenga suficiente RAM libre para el caché del disco). Sugiero esto:

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 buena solución: ACL

La buena solución puede ser completamente diferente: si los archivos se crean en este directorio (y no se mueven de otro lugar), las ACL pueden hacer el trabajo sobre la marcha. Solo tiene que establecer las ACL predeterminadas en el directorio principal.

Se pueden lograr mejoras adicionales mediante las optimizaciones del sistema de archivos. Si es ext3 / ext4, puede ejecutar e2fsck -Dde vez en cuando. Tal vez sea útil colocar este directorio en un volumen separado. Puede probar diferentes sistemas de archivos o configuraciones del sistema de archivos (por ejemplo, diferentes tamaños de inodo).

Hauke ​​Laging
fuente
Las ACL son buenas siempre que no esté trabajando en un montaje NFSv4.
ostrokach
La findsolución casi duplicó mi tiempo, chmoddentro de un contenedor acoplable.
Nathan ReinstateMonica Arthur
8

Suponiendo que el uso de chmodDel paquete GNU coreutils en Ubuntu 12.10.

chmod 775 . -Rejecuta la fchmodatllamada del sistema para cada archivo que encuentra, independientemente de si los permisos deben cambiarse o no. Confirmé esto inspeccionando el código y usando strace chmod 775 . -R(fragmento a continuación) para enumerar el comportamiento real.

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

Hay un par de desventajas de ejecutar fchmodaten cada archivo

  • La llamada adicional al sistema probablemente se volverá significativa si se cambia una gran cantidad de archivos. El método find/ xargs/ chmodmencionado por otros probablemente será más rápido al cambiar solo los archivos que deben cambiarse.
  • La llamada a fchmodatcambia la modificación del estado del archivo (ctime) de cada archivo. Esto hará que cada archivo / inodo cambie cada vez y probablemente causará un exceso de escritura en el disco. Es posible utilizar las opciones de montaje para detener estas escrituras en exceso.

Un experimento simple muestra los cambios de ctime que ocurren para 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

Pero esto no cambia durante find/ xargs/ chmodunos minutos más tarde

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

Siempre tendería a usar la versión find/ xargs/ chmodporque find brinda más control sobre la selección de cosas.

Richm
fuente
1

La [fuente] (1) muestra que chmod(1)siempre intenta establecer el modo y luego vuelve a verificar con [fstatat (2)] (2).

Los archivos se procesan a través de [fts (3)] (3), que tiene que 'stat' todos los objetos del sistema de archivos atravesados ​​de antemano para construir su árbol de datos.

Unixlore presenta un [buen artículo] (4) donde se chmod(1)mide el tiempo contra un find/ xargsenfoque: este último gana por magnitudes.

Aquí la línea de comando adaptada a la pregunta original:

find . -print0 | xargs -0 chmod 775

Dos razones:

  1. El recorrido del sistema de archivos se desacopla de las operaciones en los archivos a través de la tubería entre los dos procesos, que incluso pueden ejecutarse en diferentes núcleos.

    1. fts(3)la operación se minimiza porque xargs(1)'aplana' el árbol de directorios.

Entonces sí: definitivamente deberías usar find/ xargs. para una solución simple

Otras opciones:

  • Juegue con la [umask] (5) y el código fuente del proceso (s) escribiendo los nuevos archivos.

  • Si está utilizando Linux, es probable que su sistema haya habilitado el inotifysubsistema del núcleo. En este caso, puede crear una secuencia de comandos de una solución eficiente a través de [inotifywait (1)] (6).


Nota al margen: a menos que desee ejecutar permisos en sus archivos, sugeriría modificar la invocación de la siguiente manera:

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

Nota para los editores: no se me permite agregar más de dos enlaces a la publicación, ni comentar en otras publicaciones. Dejo las URL aquí y espero que algún usuario de corazón abierto con suficiente reputación los vuelva a incluir en el texto y elimine este párrafo.


Comente sobre cebar el caché del disco con find . -printf "":

Esto podría acelerar la ejecución de las siguientes chmodoperaciones, sin embargo, depende de la memoria disponible y la carga de E / S. Entonces podría funcionar, o no. El desacoplamiento transversal ( find) y la chmodoperación ya proporcionan almacenamiento en caché, por lo que cebar el caché puede ser superfluo.

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

¿Ha considerado cambiar los procesos que crean el archivo para que se creen con el modo 0775? Observe el valor de umask en el entorno: 0002 puede ayudar.

D McKeon
fuente