GNU/Linux >> Tutoriales Linux >  >> Linux

¿Qué define el tamaño máximo para un solo argumento de comando?

Tenía la impresión de que la longitud máxima de un solo argumento no era el problema aquí, sino el tamaño total de la matriz de argumentos general más el tamaño del entorno, que está limitado a ARG_MAX . Por lo tanto, pensé que algo como lo siguiente tendría éxito:

env_size=$(cat /proc/$$/environ | wc -c)
(( arg_size = $(getconf ARG_MAX) - $env_size - 100 ))
/bin/echo $(tr -dc [:alnum:] </dev/urandom | head -c $arg_size) >/dev/null

Con el - 100 siendo más que suficiente para dar cuenta de la diferencia entre el tamaño del entorno en el shell y el echo proceso. En su lugar, recibí el error:

bash: /bin/echo: Argument list too long

Después de jugar un rato, descubrí que el máximo era un orden de magnitud hexadecimal completo más pequeño:

/bin/echo 
  $(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) 
  >/dev/null

Cuando se elimina el menos uno, vuelve el error. Aparentemente, el máximo para un solo argumento es en realidad ARG_MAX/16 y el -1 da cuenta del byte nulo colocado al final de la cadena en la matriz de argumentos.

Otro problema es que cuando se repite el argumento, el tamaño total de la matriz de argumentos puede estar más cerca de ARG_MAX , pero todavía no del todo:

args=( $(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) )
for x in {1..14}; do
  args+=( ${args[0]} )
done

/bin/echo "${args[@]}" "${args[0]:6534}" >/dev/null

Usando "${args[0]:6533}" aquí hace que el último argumento sea 1 byte más largo y hace que la Argument list too long error. Es poco probable que esta diferencia se deba al tamaño del entorno dado:

$ cat /proc/$$/environ | wc -c
1045

Preguntas:

  1. ¿Es correcto este comportamiento o hay un error en alguna parte?
  2. Si no es así, ¿este comportamiento está documentado en alguna parte? ¿Hay otro parámetro que defina el máximo para un solo argumento?
  3. ¿Este comportamiento se limita a Linux (o incluso a versiones particulares de este)?
  4. ¿Qué explica la discrepancia adicional de ~5 KB entre el tamaño máximo real de la matriz de argumentos más el tamaño aproximado del entorno y ARG_MAX ?

Información adicional:

uname -a
Linux graeme-rock 3.13-1-amd64 #1 SMP Debian 3.13.5-1 (2014-03-04) x86_64 GNU/Linux

Respuesta aceptada:

Respuestas

  1. Definitivamente no es un error.
  2. El parámetro que define el tamaño máximo para un argumento es MAX_ARG_STRLEN . No hay documentación para este parámetro aparte de los comentarios en binfmts.h :

    /*
     * These are the maximum length and maximum number of strings passed to the
     * execve() system call.  MAX_ARG_STRLEN is essentially random but serves to
     * prevent the kernel from being unduly impacted by misaddressed pointers.
     * MAX_ARG_STRINGS is chosen to fit in a signed 32-bit integer.
     */
    #define MAX_ARG_STRLEN (PAGE_SIZE * 32)
    #define MAX_ARG_STRINGS 0x7FFFFFFF
    

    Como se muestra, Linux también tiene un límite (muy grande) en la cantidad de argumentos para un comando.

  3. Un límite en el tamaño de un único argumento (que difiere del límite general de argumentos más el entorno) parece ser específico de Linux. Este artículo ofrece una comparación detallada de ARG_MAX y equivalentes en sistemas similares a Unix. MAX_ARG_STRLEN se discute para Linux, pero no se menciona ningún equivalente en ningún otro sistema.

    El artículo anterior también establece que MAX_ARG_STRLEN se introdujo en Linux 2.6.23, junto con una serie de otros cambios relacionados con los máximos de argumentos de comando (discutidos a continuación). El registro/diff para la confirmación se puede encontrar aquí.

  4. Todavía no está claro qué explica la discrepancia adicional entre el resultado de getconf ARG_MAX y el tamaño máximo posible real de los argumentos más el entorno. La respuesta relacionada de Stephane Chazelas sugiere que parte del espacio está representado por punteros a cada una de las cadenas de argumento/entorno. Sin embargo, mi propia investigación sugiere que estos punteros no se crean al principio del execve llamada al sistema cuando aún puede devolver un E2BIG error en el proceso de llamada (aunque los punteros a cada argv ciertamente se crean más tarde).

    Además, las cadenas son contiguas en la memoria hasta donde puedo ver, por lo que no hay espacios de memoria debidos a la alineación aquí. Aunque es muy probable que sea un factor dentro de lo que hace utilizar la memoria adicional. Entender qué usa el espacio extra requiere un conocimiento más detallado de cómo el kernel asigna la memoria (que es un conocimiento útil, por lo que investigaré y actualizaré más adelante).

Relacionado:¿Cuál es la diferencia entre punto y coma y doble ampersand &&?

ARG_MAX Confusión

Desde Linux 2.6.23 (como resultado de este compromiso), ha habido cambios en la forma en que se manejan los máximos de argumentos de comando, lo que hace que Linux sea diferente de otros sistemas similares a Unix. Además de agregar MAX_ARG_STRLEN y MAX_ARG_STRINGS , el resultado de getconf ARG_MAX ahora depende del tamaño de la pila y puede ser diferente de ARG_MAX en limits.h .

Normalmente el resultado de getconf ARG_MAX será 1/4 del tamaño de la pila. Considere lo siguiente en bash usando ulimit para obtener el tamaño de la pila:

$ echo $(( $(ulimit -s)*1024 / 4 ))  # ulimit output in KiB
2097152
$ getconf ARG_MAX
2097152

Sin embargo, el comportamiento anterior cambió ligeramente con esta confirmación (agregada en Linux 2.6.25-rc4~121). ARG_MAX en limits.h ahora sirve como un límite inferior estricto en el resultado de getconf ARG_MAX . Si el tamaño de la pila se establece de forma que 1/4 del tamaño de la pila es menor que ARG_MAX en limits.h , luego limits.h se utilizará el valor:

$ grep ARG_MAX /usr/include/linux/limits.h 
#define ARG_MAX       131072    /* # bytes of args + environ for exec() */
$ ulimit -s 256
$ echo $(( $(ulimit -s)*1024 / 4 ))
65536
$ getconf ARG_MAX
131072

Tenga en cuenta también que si el tamaño de la pila se establece por debajo del mínimo posible ARG_MAX , luego el tamaño de la pila (RLIMIT_STACK ) se convierte en el límite superior del tamaño del argumento/entorno antes de E2BIG se devuelve (aunque getconf ARG_MAX seguirá mostrando el valor en limits.h ).

Una última cosa a tener en cuenta es que si el núcleo se construye sin CONFIG_MMU (soporte para hardware de administración de memoria), luego la verificación de ARG_MAX está deshabilitado, por lo que el límite no se aplica. Aunque MAX_ARG_STRLEN y MAX_ARG_STRINGS todavía aplica.

Lecturas adicionales

  • Respuesta relacionada de Stephane Chazelas:https://unix.stackexchange.com/a/110301/48083
  • En una página detallada que cubre la mayor parte de lo anterior. Incluye una tabla de ARG_MAX (y equivalentes) valores en otros sistemas similares a Unix:http://www.in-ulm.de/~mascheck/various/argmax/
  • Al parecer, la introducción de MAX_ARG_STRLEN causó un error con Automake que estaba incrustando scripts de shell en Makefiles usando sh -c – http://www.mail-archive.com/[email protected]/msg05522.html

Linux
  1. ¿Cuál es el equivalente del comando updatedb de Linux para Mac?

  2. ¿Cuál es la unidad de tamaño predeterminada en el comando linux ls -l?

  3. ¿Para qué sirve Linux test -a command test?

  4. Cambié la RUTA, ahora recibo el comando no encontrado para todo

  5. ¿Cuál es el propósito de cd ` (comilla grave)?

¿Qué es el comando Watch de Linux + ejemplos?

¿Qué es el comando matar en Linux?

¿Cuál es el comando más confiable para encontrar el tamaño real de un archivo de Linux?

¿Cuál es el equivalente al comando de archivo de Linux para Windows?

¿Qué constituye un 'campo' para el comando de corte?

¿Cuál es el uso de la opción -o en el comando useradd?