Pesquisar

Pesquisar

Esse:

#!/bin/bash

# Run command ~100Kbytes long
/bin/echo $(perl -e 'print "x"x100000') | wc
# Run command ~54Kbytes long
# This line fails: line 7: /bin/echo: Argument list too long
/bin/echo $(perl -e 'print "x "x27000') | wc

# Same command, but run using xargs
# Run command ~100Kbytes long
perl -e 'print "x"x100000' | xargs -n 100000 /bin/echo | wc
# Run command ~54Kbytes long
# This line fails: xargs: /bin/echo: Argument list too long
perl -e 'print "x "x27000' | xargs -n 100000 /bin/echo | wc

funciona bem no GNU/Linux, mas as 2 linhas de 54 Kbytes falham no MacOS X.

ARG_MAXé muito maior que 100 KBytes, e observe que as linhas de 100 Kbytes nãonãofalhar - é a linha de 54KBytes que falha.

mac$ getconf ARG_MAX
262144
mac$ uname -a
Darwin macosx 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:26:45 PDT 2012; root:xnu-1699.32.7~1/RELEASE_I386 i386
# Kusalananda suggests it may be due to the size of the environment
mac$ env | wc
      27      32     956

Por que o comando 54Kbytes falha?

Existe uma maneira de prever se a lista de argumentos é muito longa para o MacOS X sem executá-la?

Pesquisar

Esse:

#!/bin/bash

runtest() {
    echo environment size:
    env | wc
    echo Run command ~100Kbytes long
    /bin/echo $(perl -e 'print "x"x100000') | wc
    echo Run command ~54Kbytes long
    # This line fails: line 7: /bin/echo: Argument list too long
    /bin/echo $(perl -e 'print "x "x27000') | wc
    
    # Same command, but run using xargs
    echo Run command ~100Kbytes long
    perl -e 'print "x"x100000' | xargs -n 100000 /bin/echo | wc
    echo Run command ~54Kbytes long
    # This line fails: xargs: /bin/echo: Argument list too long
    perl -e 'print "x "x27000' | xargs -n 100000 /bin/echo | wc
    echo
}

# Clean environment
runtest

# Make a huge environment
for a in `seq 5000`; do eval "a$a=1" ; done
for a in `seq 5000`; do eval "a$a() { 1; }" ; done
# This works as before
runtest

# Export environment
for a in `seq 5000`; do eval export a$a ; done
for a in `seq 5000`; do eval export -f a$a ; done
# Now the 100Kbytes commands fail, too
runtest

fornece esta saída:

environment size:
    6027    6032   47849
Run command ~100Kbytes long
       1       1  100001
Run command ~54Kbytes long
test: line 10: /bin/echo: Argument list too long
       0       0       0
Run command ~100Kbytes long
       1       1  100001
Run command ~54Kbytes long
xargs: /bin/echo: Argument list too long
       0       0       0

environment size:
    6027    6032   47849
Run command ~100Kbytes long
       1       1  100001
Run command ~54Kbytes long
test: line 10: /bin/echo: Argument list too long
       0       0       0
Run command ~100Kbytes long
       1       1  100001
Run command ~54Kbytes long
xargs: /bin/echo: Argument list too long
       0       0       0

environment size:
   16027   26032  126742
Run command ~100Kbytes long
test: line 7: /bin/echo: Argument list too long
       0       0       0
Run command ~54Kbytes long
test: line 10: /bin/echo: Argument list too long
       0       0       0
Run command ~100Kbytes long
xargs: insufficient space for argument
       0       0       0
Run command ~54Kbytes long
xargs: /bin/echo: Argument list too long
       0       0       0

Então Kusalananda está certo ao dizer que oexportadoambiente pode ter um efeito. Não está claro qual é a fórmula para calcular isso: talvez seja apenas o tamanho? Talvez o número de variáveis ​​também seja importante? Talvez sejam apenas os comprimentos dos nomes? Talvez uma combinação linear disso?

Istoaindanão explica que em um determinado ambiente um comando de 100Kbytes funciona bem, mas um comando de 54Kbytes não.

É como se o MacOS não só tivesse um limite no tamanho total, mas também no número de argumentos.

Os números também fariam sentido se o MacOS usasse 8 bytes adicionais por argumento:

# One big argument
100K * "x" = 100000+2 < 262144 # Works
# 27K small arguments
27K * "x " = 27K*(8+2) > 262144 # Fails
# 26K small arguments
26K * "x " = 26K*(8+2) < 262144 # Works

Mas o MacOS faz isso?

Responder1

Outras pesquisas indicam (versão do MacOS desconhecida):

Effective length = 
  length of arguments +
  5 * number of arguments +
  length of body/value of exported functions/variables +
  length of names of exported functions/variables +
  4 * number of exported functions/variables

Se o comprimento efetivo for <256 Kbytes, o comando será executado. Não está claro se isso é verdade para todas as versões do MacOS.

Para MacOS El Capitan 10.11.4, isso fornece o comprimento pessimista da linha de comando (assumindo que o comando que você deseja executar é is /bin/echo x x x x ...):

perl -e '                                                                             
  $envc=(keys %ENV);                                                                    
  $envn=length join"",(keys %ENV);                                                      
  $envv=length join"",(values %ENV);                                                    
  $maxlen=3+(262144 - $envn - $envv) / 5 - $envc*2;                                     
  print("Max len = $maxlen\n");
'                                                        

Não está claro se isso é verdade para todas as versões do MacOS.

informação relacionada