如何导致“参数列表太长”错误?

如何导致“参数列表太长”错误?

问题的背景:根据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_MAXulimit -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/echox

注意每个参数以 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_MAX2097152(2,097,152,大约 200 万),但命令仍然错误。

如果你的 shell 没有{start..end},你可以使用稍微慢一些的(但仍然比列出文件更快)

/bin/echo $(seq 1 200000)

如果任一命令不起作用,只需增加最终值,直到它起作用,直到bash内存不足,或者直到seq无法计数为止。

相关内容