“Lista de argumentos muito longa”: Como faço para lidar com isso sem alterar meu comando?

15

Quando executo um comando como ls */*/*/*/*.jpg , recebo o erro

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

Eu sei porque isso acontece: é porque existe um limite de kernel na quantidade de espaço para argumentos para um comando. O conselho padrão é alterar o comando que uso, para evitar exigir muito espaço para argumentos (por exemplo, use find e xargs ).

E se eu não quiser alterar o comando? E se eu quiser continuar usando o mesmo comando? Como posso fazer as coisas "simplesmente funcionarem", sem receber esse erro? Quais soluções estão disponíveis?

    
por D.W. 16.08.2012 / 01:08

3 respostas

18

No Linux, a quantidade máxima de espaço para argumentos de comando é 1/4 da quantidade de espaço disponível na pilha. Então, uma solução é aumentar a quantidade de espaço disponível para a pilha.

Versão resumida: execute algo como

ulimit -s 65536

Versão mais longa: A quantidade padrão de espaço disponível para a pilha é algo como 8192 KB. Você pode ver a quantidade de espaço disponível, da seguinte maneira:

$ ulimit -s
8192

Escolha um número maior e defina a quantidade de espaço disponível para a pilha. Por exemplo, se você quiser tentar permitir até 65536 KB para a pilha, execute isto:

$ ulimit -s 65536

Você pode precisar brincar com o tamanho necessário, usando a tentativa e erro. Em muitos casos, essa é uma solução rápida e suja que elimina a necessidade de modificar o comando e elaborar a sintaxe de find , xargs , etc. (embora eu saiba que há outros benefícios em fazer isso) .

Eu acredito que isso é específico do Linux. Eu suspeito que provavelmente não vai ajudar em qualquer outro sistema operacional Unix (não testado).

    
por 16.08.2012 / 01:11
1

Este artigo do Linux Journal oferece 4 soluções. Apenas a quarta solução não envolve a alteração do comando:

Method #4 involves manually increasing the number of pages that are allocated within the kernel for command-line arguments. If you look at the include/linux/binfmts.h file, you will find the following near the top:

/*
 * 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

In order to increase the amount of memory dedicated to the command-line arguments, you simply need to provide the MAX_ARG_PAGES value with a higher number. Once this edit is saved, simply recompile, install and reboot into the new kernel as you would do normally.

On my own test system I managed to solve all my problems by raising this value to 64. After extensive testing, I have not experienced a single problem since the switch. This is entirely expected since even with MAX_ARG_PAGES set to 64, the longest possible command line I could produce would only occupy 256KB of system memory--not very much by today's system hardware standards.

The advantages of Method #4 are clear. You are now able to simply run the command as you would normally, and it completes successfully. The disadvantages are equally clear. If you raise the amount of memory available to the command line beyond the amount of available system memory, you can create a D.O.S. attack on your own system and cause it to crash. On multiuser systems in particular, even a small increase can have a significant impact because every user is then allocated the additional memory. Therefore always test extensively in your own environment, as this is the safest way to determine if Method #4 is a viable option for you.

Concordo que a limitação é seriamente irritante.

    
por 26.11.2015 / 23:53
1

Em vez de ls */*/*/*/*.jpg , tente:

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

xargs (1) sabe qual é o número máximo de argumentos no sistema e dividirá sua entrada padrão para chamar a linha de comando especificada várias vezes sem mais argumentos do que esse limite, o que quer que seja (você também pode configurá-lo abaixo do máximo do sistema operacional usando a opção -n ).

Por exemplo, suponha que o limite seja de 3 argumentos e você tenha cinco arquivos. Nesse caso, xargs executará ls duas vezes:

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

Geralmente isso é perfeitamente adequado, mas nem sempre - por exemplo, você não pode confiar em ls (1) classificação de todas as entradas para você corretamente, porque cada ls separado -volocação classificará apenas o subconjunto de entradas dadas por xargs .

Embora você possa ultrapassar o limite sugerido por outras pessoas, ainda haverá um limite - e algum dia sua coleção JPG será superada novamente. Você deve preparar seu script para lidar com um número infinito ...

    
por 05.07.2017 / 16:25