Ser*_*nyy 14 command-line shell ulimit
问题的上下文:根据POSIX 规范, ARG_MAX 是函数系列的命令行参数的最大长度exec()。这让我相信这是实际的参数数量,但这显然不起作用:
$ ulimit -s
8192
$ touch {1..18000}.jpg
$ rm *.jpg
$
Run Code Online (Sandbox Code Playgroud)
显然,尽管长度超过 8192 个项目,但效果很好。根据DW 的回答,8192应该以 kB 为单位的大小。很明显,之前的假设是错误的。
这是实际的问题进来:我如何找出项目的实际金额将获得上述8192 KB的限制?换句话说,我必须执行什么样的计算才能确保这种*.jpg类型的 glob 会导致Argument list too long错误?
请注意,这不是What 定义单个命令参数的最大大小的副本。我知道getconf ARG_MAX和ulimit -s价值观,这不是我的问题。我需要知道如何生成大小超过 limit 的足够多的参数。换句话说,我需要找到一种方法来获取错误,而不是避免它。
Kus*_*nda 10
利用getconf ARG_MAX以产生一个长长的清单x,并要求与作为它的参数会产生“参数列表太长”错误的外部工具:
$ /bin/echo $( perl -e 'print "x" x $ARGV[0]' "$(getconf ARG_MAX)" )
/bin/sh: /bin/echo: Argument list too long
Run Code Online (Sandbox Code Playgroud)
环境和字符串的长度/bin/echo将包含在导致错误发生的原因中,因此我们可以尝试通过减去这些来找到最大可能的数字:
$ env
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin
Run Code Online (Sandbox Code Playgroud)
(我用 开始这个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
Run Code Online (Sandbox Code Playgroud)
还是太长了。到多少?
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
Run Code Online (Sandbox Code Playgroud)
此循环为 退出i=8。
因此,有四个字节,我不能马上解释(八四个必须是名称的的PATH环境变量)。这些都为四根弦的空终结PATH,价值PATH,/bin/echo和长串x字符。
请注意,每个参数都以空字符结尾,因此命令的参数越多,它们的组合长度就越短。
另外,只是为了展示一个大环境的效果:
$ 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
Run Code Online (Sandbox Code Playgroud)
在许多 Linux 发行版上,您可以通过运行来找出 ARG_MAX 的当前值
getconf ARG_MAX
Run Code Online (Sandbox Code Playgroud)
生成消息“参数列表太长”的一种简单方法是实际提供一个长参数列表;例如,在我的系统上
/bin/echo "$(find / -xdev 2> /dev/null)"
Run Code Online (Sandbox Code Playgroud)
有效,但是
/bin/echo "$(find / -xdev 2> /dev/null)" "$(find / -xdev 2> /dev/null)"
Run Code Online (Sandbox Code Playgroud)
产生
bash: /bin/echo: Argument list too long
Run Code Online (Sandbox Code Playgroud)
如需深入讨论,请参阅Stack Overflow 上的“ rm, cp, mv 命令的参数列表太长错误”。
PS 有问题的长度是存储参数和环境所需的实际内存量。它与参数的数量无关。
不是列出系统上的所有文件,这需要永远并且不适用于稀疏系统,命令
/bin/echo {1..200000}
Run Code Online (Sandbox Code Playgroud)
是一种更快(163 毫秒)的产生错误的方式。对我来说ARG_MAX是2097152(2,097,152 大约 200 万)但命令仍然错误。
如果您的 shell 没有{start..end},您可以使用稍慢的(但仍然比列出文件快)
/bin/echo $(seq 1 200000)
Run Code Online (Sandbox Code Playgroud)
如果任一命令不起作用,只需增加最终值,直到它起作用,直到bash内存耗尽,或者直到seq无法计数为止。
为了更轻松地启动一个新的 shell(exit完成后)并将限制设置为较低的值(100kbytes):
$ bash
$ ulimit -s 100
Run Code Online (Sandbox Code Playgroud)
对于您使用的示例,可能会触发错误:
$ touch {1..100000}.jpg
bash: /usr/bin/touch: Argument list too long
Run Code Online (Sandbox Code Playgroud)
但最好使用类似echo. 了解内置程序可能不会触发错误,此命令应该可以正常工作:
$ echo {000001..100000}6789
Run Code Online (Sandbox Code Playgroud)
另请注意,字节数远远超过上面设置的限制(1.1Mbyte):
$ echo {000001..100000}6789 | wc -c
1100000
Run Code Online (Sandbox Code Playgroud)
但是这个命令不起作用:
$ /bin/echo {000001..100000}6789
bash: /bin/echo: Argument list too long
Run Code Online (Sandbox Code Playgroud)
该限制由添加到 shell 环境大小的参数列表的大小(以字节为单位)设置。