
Этот:
#!/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
отлично работает на GNU/Linux, но 2 строки по 54 Кбайт не работают на MacOS X.
ARG_MAX
намного больше, чем 100 Кбайт, и, пожалуйста, обратите внимание, что строки по 100 Кбайт ненетсбой - это строка 54 Кбайт, которая дает сбой.
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
Почему команда 54Kbytes не выполняется?
Есть ли способ предсказать, слишком ли длинный список аргументов для MacOS X, не запуская его?
Исследовать
Этот:
#!/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
дает такой вывод:
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
Итак, Кусалананда прав, чтоэкспортированоокружающая среда может иметь эффект. Неясно, какая формула используется для вычисления этого: Может быть, это просто размер? Может быть, количество переменных тоже важно? Может быть, это только длина имен? Может быть, линейная комбинация того и другого?
Этовсе ещене объясняет, что в данной среде команда размером 100 Кбайт работает нормально, а команда размером 54 Кбайт — нет.
Как будто в MacOS есть ограничение не только на общий размер, но и на количество аргументов.
Цифры также имели бы смысл, если бы MacOS использовала дополнительные 8 байт на аргумент:
# 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
Но делает ли это MacOS?
решение1
Дальнейшие исследования показывают (версия MacOS неизвестна):
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
Если эффективная длина < 256 Кбайт, команда будет выполнена. Неясно, справедливо ли это для всех версий MacOS.
Для MacOS El Capitan 10.11.4 это дает пессимистическую длину командной строки (предполагая, что команда, которую вы хотите выполнить, это /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");
'
Неясно, относится ли это ко всем версиям MacOS.