Forschung

Forschung

Das:

#!/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

funktioniert unter GNU/Linux einwandfrei, aber die beiden Zeilen mit jeweils 54 KB schlagen unter MacOS X fehl.

ARG_MAXist viel höher als 100 KBytes, und bitte beachten Sie, dass die 100 KBytes Zeilennichtfehlgeschlagen – es ist die 54-KByte-Zeile, die fehlschlägt.

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

Warum schlägt der 54-KByte-Befehl fehl?

Gibt es eine Möglichkeit, vorherzusagen, ob die Argumentliste für MacOS X zu lang ist, ohne es auszuführen?

Forschung

Das:

#!/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

gibt diese Ausgabe aus:

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

Kusalananda hat also recht, dass dieexportiertUmgebung kann einen Einfluss haben. Es ist unklar, wie die Formel lautet, um dies zu berechnen: Vielleicht ist es nur die Größe? Vielleicht ist auch die Anzahl der Variablen wichtig? Vielleicht ist es nur die Länge der Namen? Vielleicht eine lineare Kombination davon?

EsTrotzdemerklärt nicht, dass in einer bestimmten Umgebung ein 100-KByte-Befehl einwandfrei funktioniert, ein 54-KByte-Befehl jedoch nicht.

Es ist, als ob MacOS nicht nur eine Beschränkung der Gesamtgröße, sondern auch eine Beschränkung der Anzahl der Argumente hätte.

Die Zahlen würden auch Sinn ergeben, wenn MacOS zusätzliche 8 Bytes pro Argument verwenden würde:

# 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

Aber macht MacOS das?

Antwort1

Weitere Untersuchungen ergeben (MacOS-Version unbekannt):

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

Wenn die effektive Länge < 256 KBytes ist, wird der Befehl ausgeführt. Es ist unklar, ob dies für alle Versionen von MacOS gilt.

Für MacOS El Capitan 10.11.4 ergibt dies die pessimistische Befehlszeilenlänge (vorausgesetzt, der Befehl, den Sie ausführen möchten, ist /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");
'                                                        

Es ist unklar, ob dies für alle Versionen von MacOS gilt.

verwandte Informationen