问题的背景:根据POSIX 规范, ARG_MAX 为最大值长度函数族的命令行参数exec()
。这让我相信这是真实的数字的论点,但这显然不起作用:
$ ulimit -s
8192
$ touch {1..18000}.jpg
$ rm *.jpg
$
显然,尽管长度超过 8192 项,但效果很好。根据DW的回答,8192
据说大小以 kB 为单位。很明显,之前的假设是错误的。
这就是实际问题所在:我如何计算出实际的物品数量将要超过 8192 kB 限制?换句话说,我必须执行什么样的计算才能确保该*.jpg
类型的 glob 会导致Argument list too long
错误?
请注意,这不是重复的什么定义了单个命令参数的最大大小。我了解getconf ARG_MAX
并ulimit -s
价值观,这不是我的问题。我需要知道如何生成足够多的参数,其大小将高于限制。换句话说,我需要找到一种方法来获取错误,而不是避免错误。
答案1
使用getconf ARG_MAX
生成长列表x
并以此作为参数调用外部实用程序将生成“参数列表太长”错误:
$ /bin/echo $( perl -e 'print "x" x $ARGV[0]' "$(getconf ARG_MAX)" )
/bin/sh: /bin/echo: Argument list too long
环境和字符串的长度/bin/echo
将包含在导致错误发生的原因中,因此我们可以尝试通过减去这些来找到最大可能的数字:
$ env
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin
(我用 启动了这个 shell ,所以环境中env -i sh
只有变量)PATH
$ /bin/echo $( perl -e 'print "x" x ($ARGV[0] - length($ENV{"PATH"}) - length("/bin/echo"))' "$(getconf ARG_MAX)" )
sh: /bin/echo: Argument list too long
还是太长了。多少?
i=0
while ! /bin/echo $( perl -e 'print "x" x ($ARGV[0] - length($ENV{"PATH"}) - length("/bin/echo") - $ARGV[1])' "$(getconf ARG_MAX)" "$i" )
do
i=$(( i + 1 ))
done
该循环退出 for i=8
。
因此,有四个字节我无法立即解释(八个字节中的四个必须用于姓名环境PATH
变量)。这些是四个字符串、的PATH
值和长字符串的空终止符。PATH
/bin/echo
x
注意每个参数以 null 结尾,因此命令的参数越多,它们的组合长度就越短。
另外,只是为了展示大环境的效果:
$ export BIG=$( perl -e 'print "x" x $ARGV[0]' "$( getconf ARG_MAX )" )
$ /bin/echo hello
sh: /bin/echo: Argument list too long
$ /bin/echo
sh: /bin/echo: Argument list too long
答案2
在许多 Linux 发行版上,您可以通过运行以下命令来了解 ARG_MAX 的当前值:
getconf ARG_MAX
生成消息“参数列表太长”的一个简单方法是实际提供一个长参数列表;例如,在我的系统上
/bin/echo "$(find / -xdev 2> /dev/null)"
有效,但是
/bin/echo "$(find / -xdev 2> /dev/null)" "$(find / -xdev 2> /dev/null)"
产生
bash: /bin/echo: Argument list too long
如需深入讨论,请参阅“rm、cp、mv 命令的参数列表太长错误” 在堆栈溢出上。
PS 所讨论的长度是存储参数和环境所需的实际内存量。它与以下内容无关数字的论点。
答案3
为了更容易地启动一个新的 shell(exit
完成后)并将限制设置为较低的值(100kbytes):
$ bash
$ ulimit -s 100
使用您使用的示例,可能会触发错误:
$ touch {1..100000}.jpg
bash: /usr/bin/touch: Argument list too long
但最好使用类似的东西echo
。了解内置命令可能不会触发错误,此命令应该可以正常工作:
$ echo {000001..100000}6789
另请注意,字节数远超过上面设置的限制(1.1Mbyte):
$ echo {000001..100000}6789 | wc -c
1100000
但这个命令不起作用:
$ /bin/echo {000001..100000}6789
bash: /bin/echo: Argument list too long
该限制由添加到 shell 环境大小的参数列表的大小(以字节为单位)设置。
答案4
该命令不是列出系统上的所有文件,这需要很长时间并且在稀疏系统上不起作用
/bin/echo {1..200000}
是一种更快(163ms)的产生错误的方法。对我来说ARG_MAX
是2097152
(2,097,152,大约 200 万),但命令仍然错误。
如果你的 shell 没有{start..end}
,你可以使用稍微慢一些的(但仍然比列出文件更快)
/bin/echo $(seq 1 200000)
如果任一命令不起作用,只需增加最终值,直到它起作用,直到bash
内存不足,或者直到seq
无法计数为止。