
這:
#!/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 54Kbytes 行在 MacOS X 上失敗。
ARG_MAX
遠高於 100KBytes,請注意 100Kbytes 行確實不是失敗 - 54KBytes 線路失敗。
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
所以,庫薩羅南達是對的出口環境可以產生影響。目前還不清楚計算這個的公式是什麼:也許純粹是大小?也許變數的數量也很重要?也許只是名字的長度?也許是這些的線性組合?
它仍然沒有解釋在給定環境中 100Kbytes 命令可以正常工作,但 54Kbytes 命令則不能。
就好像 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 KB,則命令將運行。目前尚不清楚這是否適用於所有版本的 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。