“ Lista de argumentos demasiado larga ”: ¿Cómo lo manejo sin cambiar mi comando?

Cuando ejecuto un comando como ls */*/*/*/*.jpg, aparece el error

-bash: /bin/ls: Argument list too long 

Sé por qué sucede esto: es porque hay un límite de kernel en la cantidad de espacio para argumentos de un comando. El consejo estándar es cambiar el comando que uso, para evitar requerir tanto espacio para los argumentos (por ejemplo, use find y xargs).

¿Qué pasa si no quiero cambiar el comando? ¿Qué pasa si quiero seguir usando el mismo comando? ¿Cómo puedo hacer que las cosas «simplemente funcionen» sin que aparezca este error? ¿Qué soluciones hay disponibles?

Comentarios

  • Lectura útil: Bash FAQ 95 . Sin cambiar su comando ‘ no hay mucho que pueda hacer además de recompilar para aumentar el tamaño máximo de su lista de argumentos, o cambiar la estructura de su directorio para que haya menos archivos.
  • @ jw013 basado en la versión del kernel de Linux, es posible aumentar la lista de argumentos; consulte unix.stackexchange.com/a/45161/8979 para obtener detalles sobre el cambio en sistemas recientes.
  • @UlrichDangel, ¡Sí, es posible! Vea mi respuesta; mi respuesta muestra cómo hacerlo (en L inux, con un kernel lo suficientemente reciente).

Respuesta

En Linux, la cantidad máxima de espacio para el comando argumentos es 1/4 de la cantidad de espacio de pila disponible. Entonces, una solución es aumentar la cantidad de espacio disponible para la pila.

Versión corta: ejecute algo como

ulimit -s 65536 

Versión más larga : La cantidad predeterminada de espacio disponible para la pila es algo así como 8192 KB. Puede ver la cantidad de espacio disponible, de la siguiente manera:

$ ulimit -s 8192 

Elija un número mayor y establezca la cantidad de espacio disponible para la pila. Por ejemplo, si desea intentar permitir hasta 65536 KB para la pila, ejecute esto:

$ ulimit -s 65536 

Es posible que deba jugar con el tamaño que necesita ser, usando prueba y error. En muchos casos, esta es una solución rápida y sucia que eliminará la necesidad de modificar el comando y resolver la sintaxis de find, xargs, etc. (aunque me doy cuenta de que hay otros beneficios al hacerlo).

Creo que esto es específico de Linux. Sospecho que probablemente no ayudará en ningún otro sistema operativo Unix (no probado).

Comentarios

  • Puede verificar así que funcionó : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • ¿Significa esto que si hago que el tamaño de la pila sea ilimitado con ulimit -s unlimited el tamaño de la línea de comandos será ¿ilimitado también?

Responder

En lugar de ls */*/*/*/*.jpg, intente:

echo */*/*/*/*.jpg | xargs ls 

xargs (1) sabe cuál es el número máximo de argumentos en el sistema y dividirá su entrada estándar para llamar a la línea de comando especificada varias veces sin más argumentos que ese límite, cualquiera que sea (también puede establecerlo por debajo del máximo del sistema operativo utilizando -n opción).

Por ejemplo, suponga que el límite es de 3 argumentos y tiene cinco archivos. En ese caso, xargs ejecutará ls dos veces:

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

A menudo, esto es perfectamente adecuado, pero no siempre; por ejemplo, no puede confíe en ls (1) ordenar todas las entradas correctamente, porque cada ls -invocación clasificará solo el subconjunto de entradas que le proporcione xargs.

Aunque puede superar el límite según lo sugerido por otros, todavía habrá un límite: y algún día tu colección JPG volverá a superarla. Debes preparar tu (s) script (s) para tratar con un número infinito …

Comentarios

  • ¡Gracias por la idea! Esta no es una mala solución. Dos advertencias: 1. Esto rompe en directorios y nombres de archivos que tienen espacios en su nombre, por lo que ‘ no es un sustituto perfecto. 2. ¿Se encontrará con el mismo problema con Argument list too long, pero para echo en lugar de ls, en shells donde echo no es un comando integrado en el shell? (Tal vez ese ‘ no sea un problema en la mayoría de los shells, así que tal vez ese ‘ sea irrelevante).
  • Sí , los caracteres especiales en los nombres de archivo son un problema. Lo mejor que puede hacer es usar find con el predicado -print0 y canalizar su salida a xargs con la opción -0.echo es un shell integrado y no sufre la limitación de la línea de comandos de exec (3).
  • Esto funciona con comandos que esperan el argumento de la variable como último parámetro, como ls, pero ¿qué hago cuando quiero mv muchos archivos en un solo directorio, por ejemplo mv * destdir? Si * da el error » demasiados argumentos «, puedo ‘ t hacer xargs pasar las rutas como la primera a mv de alguna manera, ¿o puedo?
  • Revise la página de manual para xargs en su sistema; en FreeBSD, por ejemplo, -J ayudará usted con esta tarea. Si en su sistema operativo no hay forma de hacer esto, ‘ necesitará escribir un script personalizado para reordenar los argumentos. Algo como: destdir=$1; shift; mv "$@" "$destdir". Luego, entregue este nuevo script a xargs: .... | xargs newscript $destdir

Responder

Este artículo de Linux Journal ofrece 4 soluciones. Solo la cuarta solución no implica cambiar el comando:

El método # 4 implica aumentar manualmente el número de páginas que se asignan dentro del kernel para la línea de comandos argumentos. Si observa el archivo include / linux / binfmts.h, encontrará lo siguiente cerca de la parte superior:

/* * MAX_ARG_PAGES defines the number of pages allocated for arguments * and envelope for the new program. 32 should suffice, this gives * a maximum env+arg of 128kB w/4KB pages! */ #define MAX_ARG_PAGES 32 

Para aumentar la cantidad de memoria dedicado a los argumentos de la línea de comandos, simplemente debe proporcionar el valor MAX_ARG_PAGES con un número más alto. Una vez guardada esta edición, simplemente vuelva a compilar, instalar y reiniciar en el nuevo kernel como lo haría normalmente.

En mi propio sistema de prueba logré resolver todos mis problemas elevando este valor a 64. Después de un extenso pruebas, no he experimentado un solo problema desde el cambio. Esto es completamente esperado ya que incluso con MAX_ARG_PAGES configurado en 64, la línea de comando más larga posible que podría producir solo ocuparía 256 KB de memoria del sistema, no mucho para los estándares de hardware del sistema de hoy .

Las ventajas del Método # 4 son claras. Ahora puede simplemente ejecutar el comando como lo haría normalmente, y se completa correctamente. Las desventajas son igualmente claras. Si aumenta la cantidad de memoria disponible a la línea de comandos más allá de la cantidad de memoria del sistema disponible, puede crear un ataque DOS en su propio sistema y hacer que se bloquee. En sistemas multiusuario en particular, incluso un pequeño aumento puede tener un impacto significativo porque a cada usuario se le asigna el memoria adicional. Por lo tanto, realice siempre pruebas exhaustivas en su propio entorno, ya que esta es la forma más segura de determinar si el Método 4 es una opción viable para usted.

Estoy de acuerdo en que la limitación es muy molesta.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *