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

El límite es mucho menor que la del sistema operativo (en el caso de Linux modernos).

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 puedo evitar este problema?

Actualización

Quiero señalar que getconf no puede ayudar aquí (debido a que no es un sistema de límite):

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

Actualización #2

Ahora he comprendido lo que es el punto aquí. Que no es un shell de límite, que es un sistema de límite para la longitud de cada uno de los argumentos, no a todo el arglist.

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

Gracias, CodeGnome, para la explicación.

InformationsquelleAutor Igor Chubin | 2012-07-13

5 Comentarios

  1. 21

    TL;DR

    Un solo argumento debe ser menor que la MAX_ARG_STRLEN.

    Análisis

    Según en 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 podría ser relevante si se genera una larga llamada como «sh -c ‘generados con largos argumentos'».

    Este es exactamente el «problema», identificados por el OP. Mientras que el número de argumentos puede ser muy grande (ver getconf ARG_MAX), cuando se pasa un comando entre comillas para /bin/sh el shell interpreta el comando entre comillas como una sola cadena. En el OP ejemplo, ésta es la única cadena que supera el MAX_ARG_STRLEN límite, no la longitud de la ampliación de la lista de argumentos.

    Aplicación Específica

    Argumento límites de aplicación específica. Sin embargo, este Linux artículo de Revista sugiere varias maneras de trabajar alrededor de ellos, incluyendo el aumento de los límites del sistema. Esto puede no ser directamente aplicables a la OP, pero es sin embargo útil en el caso general.

    Hacer Algo Más

    El OP problema no es realmente un problema real. La pregunta es la imposición de una restricción arbitraria que no resuelve un problema de la vida real.

    Usted puede evitar esto con bastante facilidad mediante el uso de bucles. Por ejemplo, con Bash 4:

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

    funciona bien. Sin duda, va a ser lento, ya que estamos de desove de un proceso en cada pasada por el bucle, pero sin duda consigue alrededor de la línea de comandos límite que usted está experimentando.

    Describir Su Problema Real

    Si de un bucle no resuelve su problema, por favor, actualice la pregunta para describir el problema en realidad estás tratando de resolver mediante largas listas de argumento. La exploración de línea arbitraria de longitud límites es un ejercicio académico, y no en el tema de Desbordamiento de Pila.

    • Que no es un sistema de límite! que es shell límite!
    • No tengo MAX_ARG_STRLEN en un sistema con 2.6.31
    • Yo también (3.2.0-rc7-686-pae); pero de todos modos, el argumento de longitud es el punto. La única pregunta es cómo encontrarlo.
    • Hay sistemas sin MAX_ARG_STRLEN (de mi parte y del sistema de Dennis). Así que tenemos que encontrar otra manera de encontrar este valor.
    • execve(2) dice que «En el kernel 2.6.23 y más tarde…el límite por cadena es de 32 páginas (el núcleo constante MAX_ARG_STRLEN), y el número máximo de strings es 0x7FFFFFFF.» Por lo que parece probable que su sistema no lo tiene, pero es un núcleo constante.
    • Ah, es sólo visibles para los getconf y no en limits.h (pero es en el man página). Gracias.
    • En cualquier momento. Sólo para que conste, yo también grepped las cabeceras del kernel y se encontró que se define en /usr/src/linux-headers-3.0.0-14/include/linux/binfmts.h si uno nunca debe volver a definir.
    • O si usted no tiene la fuente instalada y usted sólo tiene que mirar hacia arriba: /usr/include/linux/binfmts.h
    • Si estás en lo correcto, este sería otro tonto Linux desviación del estándar POSIX. POSIX sólo sabe una limitación: La pila inicial de un proceso que no debe exceder de ARG_MAX.

  2. 1

    No me da ese mensaje de error. Mi secreto? Las comillas simples:

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

    Si puedo usar comillas dobles, me sale 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 obtiene expandida en el shell actual cuando las comillas dobles se usan como evidencia el hecho de que Bash es quien lanza el error «-bash: …» independientemente de la cáscara se utiliza para ejecutar el comando. En mi sistema sh es Dash, por el camino.

    Esto es cierto incluso para otros «host» conchas:

    $ 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 lo hagas.

    • Dennis, individuales/dobles comillas no es un punto. He utilizado $(seq 1 100000) aquí sólo para fines de demostración; no importa cómo se produce esta larga cadena; por supuesto que necesita el doble de citas aquí porque tengo necesidad de cadena muy larga. La pregunta principal es ¿por cuánto tiempo puede ser el argumento de sh -c ''
    • La respuesta es que si importa, lo estás haciendo mal. En mi sistema, por cierto, es 131071.
    • Consulte «Hacer Algo Más» aquí.
    • Qué buena idea 🙂 pero de todos modos, supongo que CodeGnome han encontrado la respuesta correcta. El punto real es la longitud de un argumento.
    • Sólo para la integridad: /bin/bash -c '/bin/true "$(seq 1 100000)"' se rompe debido a que el shell acorta las cadenas. +1 para resolver para Y en esta X/Y problema, aunque … creo que es útil tener una publicados solución para temas relacionados.
  3. 0

    Disminución de 100.000 hasta que ya no sale el error

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

    etc.

    • muy inteligente 🙂 mejores ideas?
    • modificada por la dicotomía, ver mi respuesta
    • Creo que CodeGnome ha encontrado la solución. Ver su respuesta.
    • Lo siento, esto fue sólo un enfoque ingenuo para determinar el local de límite. Yo no estaba ofreciendo una solución 🙂
  4. 0

    Hacer que un archivo con #!/bin/sh como la primera línea, a continuación, poner el resto de su comando en las líneas posteriores? 🙂

    Más en serio, usted también puede leer los comandos de STDIN el uso de la -s opción, así que usted puede generar su larga línea de comandos y la tubería en /bin/sh -s

    • Usted puede hacer esto incluso sin -s; sí sé que probablemente es la mejor solución, excepto situaciones cuando se necesita usar el shell de stdin para algo más
    • Creo que CodeGnome ha encontrado la solución. Ver su respuesta.
    • Una especie de – excepto que todavía hay un máximo de línea de comandos de longitud, y el «por $(comando que genera gran cantidad de args); hacer; de hecho,» la estructura es una línea de comandos que puede ir por encima de esa longitud. La canalización de los comandos en la ENTRADA estándar (si con -s o con for arg in $(</dev/stdin)) es realmente la única manera real ilimitado «argumento» de apoyo.
  5. 0

    sobre mi os es la longitud máxima obtenida por la dicotomía

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

    por lo que da 131071

    pero no hay ninguna razón para tener una línea de tiempo ; si es debido a un gran número de argumentos, «[email protected]» puede ser utilizado en lugar de otro; por ejemplo

    /bin/sh -c 'command "[email protected]"' -- arg1 arg2 .. argn

Dejar respuesta

Please enter your comment!
Please enter your name here