variable script from else bash shell command-line arguments quoting

bash - script - ¿Por qué obtengo "/ bin/sh: lista de argumentos demasiado larga" al pasar los argumentos entre comillas?



if shell script (5)

¿Cuánto tiempo puede ser una línea de comando que se puede pasar a sh -c '''' ? (en bash y en bourne shell)

El límite es mucho más bajo que el del sistema operativo (en el caso de Linux moderno).

Por ejemplo:

$ /bin/true $(seq 1 100000) $ /bin/sh -c "/bin/true $(seq 1 100000)" bash: /bin/sh: Argument list too long

¿Y cómo podría evitar este problema?

Actualizar

Quiero tener en cuenta que getconf no puede ayudar aquí (porque eso no es un límite del sistema):

$ seq 1 100000 | wc -c 588895 $ getconf ARG_MAX 2097152

Actualización # 2

Ahora he entendido cuál es el punto aquí. Eso no es un límite de shell, es un límite del sistema, pero para la longitud de cada argumento, no para todo el arglista.

$ /bin/true $(seq 1 100000) $ /bin/true "$(seq 1 100000)" bash: /bin/true: Argument list too long

Gracias, CodeGnome, por la explicación.


TL; DR

Un solo argumento debe ser más corto que MAX_ARG_STRLEN.

Análisis

Según este enlace :

Y como límite adicional desde 2.6.23, un argumento no debe ser más largo que MAX_ARG_STRLEN (131072). Esto puede ser relevante si genera una llamada larga como "sh -c ''generado con argumentos largos''".

Este es exactamente el "problema" identificado por el OP. Si bien la cantidad de argumentos permitidos puede ser bastante grande (consulte getconf ARG_MAX ), cuando pasa un comando entre comillas a / bin / sh, el shell interpreta el comando entre comillas como una sola cadena. En el ejemplo del OP, es esta cadena única la que supera el límite MAX_ARG_STRLEN, no la longitud de la lista de argumentos expandida.

Implementación específica

Los límites del argumento son específicos de la implementación. Sin embargo, este artículo de Linux Journal sugiere varias formas de solucionarlos, incluido el aumento de los límites del sistema. Esto puede no ser directamente aplicable al OP, pero aún así es útil en el caso general.

Hacer algo más

El problema del OP no es realmente un problema real. La pregunta es imponer una restricción arbitraria que no resuelve un problema del mundo real.

Puede solucionar esto fácilmente utilizando bucles. Por ejemplo, con Bash 4:

for i in {1..100000}; do /bin/sh -c "/bin/true $i"; done

funciona bien Sin duda, será lento, ya que está generando un proceso en cada paso a través del bucle, pero ciertamente supera el límite de línea de comandos que está experimentando.

Describe tu problema real

Si un bucle no resuelve su problema, actualice la pregunta para describir el problema que realmente está tratando de resolver utilizando listas de argumentos realmente largas. Explorar límites de longitud de línea arbitrarios es un ejercicio académico, y no está relacionado con el tema de Desbordamiento de pila.


Cree un archivo con #!/bin/sh como la primera línea, y luego coloque el resto de su comando en las líneas siguientes. :)

Más seriamente, también puede leer los comandos de STDIN usando la opción -s , así puede generar su línea de comandos larga y canalizarla a /bin/sh -s


Disminuye 100.000 hasta que ya no recibas el error.

/bin/sh -c "/bin/true $(seq 1 99999)" /bin/sh -c "/bin/true $(seq 1 99998)"

etc.


No recibo ese mensaje de error. ¿Mi secreto? Comillas simples:

/bin/sh -c ''/bin/true $(seq 1 100000)''

Si uso comillas dobles, obtengo ese error con cada shell:

$ /bin/sh -c "/bin/true $(seq 1 100000)" -bash: /bin/sh: Argument list too long $ /bin/bash -c "/bin/true $(seq 1 100000)" -bash: /bin/bash: Argument list too long $ /bin/ksh -c "/bin/true $(seq 1 100000)" -bash: /bin/ksh: Argument list too long $ /bin/zsh -c "/bin/true $(seq 1 100000)" -bash: /bin/zsh: Argument list too long

La lista de argumentos se expande en el shell actual cuando se usan comillas dobles, como lo demuestra el hecho de que Bash es el que emite el error "-bash: ..." independientemente del shell que se utilice para ejecutar el comando. En mi sistema sh es Dash, por cierto.

Esto es válido incluso para otros shells "host":

$ dash $ /bin/bash -c ''/bin/true $(seq 1 100000)'' $ /bin/bash -c "/bin/true $(seq 1 100000)" dash: /bin/bash: Argument list too long

Paciente: Doctor, me duele cuando hago esto ".
Doctor: No hagas eso.


en mi sistema operativo es la longitud máxima obtenida por dicotomía

/bin/sh -c "/bin/true $(perl -e ''print"a"x131061'')"

por lo que da 131071

pero no hay razón para tener una línea tan larga; si se debe a una gran cantidad de argumentos, se puede usar "$ @" en su lugar; por ejemplo

/bin/sh -c ''command "$@"'' -- arg1 arg2 .. argn