Compile o kernel para aumentar o tamanho máximo da linha de comando

0

Acompanhando o link , que diz a duração máxima para argumentos de linha de exec / comando são controlados por ARG_MAX .

Então eu quero aumentar o tamanho máximo da linha de comando, e parece que recompilar o kernel é a única opção. Bem. No entanto, minha pergunta é sobre o ARG_MAX , porque todo mundo está dizendo que é o que precisa ser aumentado, mas eu li de link ,

ARG_MAX não é usado no próprio código do kernel pré-2.6.23. Post Linux 2.6.23, ARG_MAX não está mais codificado.

Então, ARG_MAX não é mais usado ou não? Como aumentar o comprimento máximo para argumentos de exec / linha de comando, então? porque o comprimento máximo da minha linha de comando é limitado a algum valor menor do que eu prefiro.

Obrigado

    
por xpt 23.01.2014 / 17:54

1 resposta

2

Como linux-2.6.23 ARG_MAX não é necessariamente uma constante predeterminada, o tamanho total dos argumentos pode ser de até 1/4 do tamanho da pilha (veja ulimit -s , tamanho da pilha em kB; mas /proc/1/limits é mais definitivo). No entanto, ARG_MAX não é apenas para os argumentos do processo, ele também contém as variáveis de ambiente, que você pode precisar levar em conta.

POSIX define o que ARG_MAX significa e um limite inferior aceitável ( _POSIX_ARG_MAX 4096). Seu valor estático é (historicamente) disponível através de um #define nos cabeçalhos do sistema, e também é definido nos cabeçalhos do kernel do Linux. Seu valor efetivo está disponível em sysconf() ou getconf ARG_MAX na linha de comando.

Se você verificar os cabeçalhos da glibc ( sys/param.h ), verá isto:

/* The kernel headers defines ARG_MAX.  The value is wrong, though.  */
#ifdef __undef_ARG_MAX
# undef ARG_MAX
# undef __undef_ARG_MAX
#endif

Isso é de glibc-2.17, isso apareceu por volta de 2.11 (2009), primeiro suporte para essas datas para 2.8 (2008), mas anterior a 2.14 (2011) houve um erro na lógica acima que impediu que funcionasse como esperado. A intenção é garantir que ARG_MAX seja indefinido, se não for uma constante, portanto, os programas devem contar com sysconf() . (Mesmo que seja definido, pode ser apenas um limite inferior garantido, e os programas devem usar sysconf() para determinar os limites superiores da variável, veja sysconf(3) )

Você pode verificar o que seu compilador C vê com ( gcc , bash / zsh somente sintaxe):

$ gcc -E -dM -x c <(echo "#include <sys/param.h>") | fgrep ARG
#define ARG_MAX 131072
#define NCARGS ARG_MAX
#define _POSIX_ARG_MAX 4096

A saída acima é de um sistema antigo (2.6.27), que possui suporte ao kernel, mas não o tempo de execução completo (suporte a glibc). Se você não vir nenhuma linha ARG_MAX , então não é um limite pré-determinado, e você deve usar (sysconf) getconf ARG_MAX :

$ getconf ARG_MAX
2097152

Uma maneira útil de verificar o suporte também é:

$ xargs --show-limits < /dev/null
Your environment variables take up 2542 bytes
POSIX upper limit on argument length (this system): 2092562
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2090020
Size of command buffer we are actually using: 131072

Isso é de um sistema linux-2.6.37 / glib-2.13 com os limites mais altos. Observe a linha final de saída, xargs defaults (tempo de compilação) para um limite "sensato", provavelmente no caso de algum dos processos iniciados não serem capazes de manipular valores muito grandes. Você pode modificar isso em tempo de execução com a opção -s . Além disso, se você tiver um ulimit -s em vigor, esses números podem ser menores. Este deve funcionar corretamente desde findutils-4.3.9 (2007). Veja também: link

Para verificar o perl:

% perl -MPOSIX -e 'print ARG_MAX . "\n"';
131072

O texto acima é novamente de um sistema antigo, um novo sistema deve mostrar:

% perl -MPOSIX -e 'print ARG_MAX . "\n"';
Your vendor has not defined POSIX macro ARG_MAX, used at -e line 1

Para resumir:

  • Se você estiver executando um kernel pós-2.6.23, o kernel permitirá que tamanhos maiores sejam passados ao criar um processo. Esta é uma condição necessária, mas não suficiente .
  • O processo pai não deve impor nenhum limite de tempo de execução incorreto (por exemplo, com ARG_MAX codificado), ele deve verificar os códigos de erro exec() E2BIG e deve usar sysconf(_SC_ARG_MAX) se necessário
  • O processo filho não deve aplicar nenhum limite de tempo de execução incorreto, em particular seu código de inicialização que processa os parâmetros fornecidos do kernel não deve ter limites codificados incorretos (por exemplo, ao configurar argc , argc , a área de ambiente tempo de uso). Isso é feito tipicamente em libc (glibc).
  • Para pai e filho, você também pode precisar configurar e construir suporte de tempo a partir da libc (ou equivalente). Para glibc isso requer pelo menos o glibc-2.8 (embora deva ser possível contorná-lo, pode não ser simples ou limpo)

Uma combinação de problemas é um kernel atualizado (linux > = 2.6.23), mas falta ou suspeita de suporte a glibc (glibc < = 2.14)

Se você estiver executando um kernel antigo, primeiro certifique-se de que seu fornecedor não tenha feito o back-port do recurso. Caso contrário, você pode, em princípio, alterar o limite do kernel e recompilar, mas você pode precisar também modificar pelo menos alguns cabeçalhos do sistema ou código-fonte para suporte ao trabalho.

Os programas devem ser capazes de manipular valores arbitrários, mas isso nem sempre é o caso: link

Applications should not assume any particular value for a limit. [...] It should be noted, however, that many of the listed limits are not invariant, and at runtime, the value of the limit may differ from those given in this header, for the following reasons:

  • The limit is pathname-dependent.
  • The limit differs between the compile and runtime machines.

For these reasons, an application may use the fpathconf(), pathconf(), and sysconf() functions to determine the actual value of a limit at runtime.

    
por 24.02.2014 / 14:46