可以传递给sh -c ''
的命令行多长时间? (在bash和bourne shell中)
该限制远低于操作系统的限制(在现代Linux的情况下)。
例如:
$ /bin/true $(seq 1 100000)
$ /bin/sh -c "/bin/true $(seq 1 100000)"
bash: /bin/sh: Argument list too long
我怎么能绕过这个问题?
更新
我想注意getconf
在这里无法帮助(因为这不是系统限制):
$ seq 1 100000 | wc -c
588895
$ getconf ARG_MAX
2097152
更新#2
现在我明白了这里有什么意义。这不是shell限制,即系统限制,但是对于每个参数的长度,而不是整个arglist。
$ /bin/true $(seq 1 100000)
$ /bin/true "$(seq 1 100000)"
bash: /bin/true: Argument list too long
感谢CodeGnome的解释。
答案 0 :(得分:21)
单个参数必须短于MAX_ARG_STRLEN。
根据this link:
作为2.6.23以来的附加限制,一个参数不得长于MAX_ARG_STRLEN(131072)。如果你生成一个长期调用,例如“使用长参数'生成的sh -c',这可能会变得相关。”
这正是OP确定的“问题”。虽然允许的参数数量可能非常大(请参阅getconf ARG_MAX
),但当您将带引号的命令传递给 / bin / sh 时,shell会将引用的命令解释为单个字符串。在OP的示例中,这个单个字符串超出了MAX_ARG_STRLEN限制,而不是扩展参数列表的长度。
参数限制是特定于实现的。但是,this Linux Journal article提出了几种解决方法,包括增加系统限制。这可能不是直接适用于OP,但它在一般情况下仍然有用。
OP的问题实际上并不是一个真正的问题。问题是强加一个不能解决现实世界问题的任意约束。
通过使用循环,您可以轻松地解决这个问题。例如,使用Bash 4:
for i in {1..100000}; do /bin/sh -c "/bin/true $i"; done
工作得很好。它肯定会很慢,因为你在循环的每次传递中产生一个进程,但它肯定会遇到你遇到的命令行限制。
如果循环无法解决您的问题,请更新问题以描述您实际尝试使用非常长的参数列表解决的问题。探索任意行长限制是一项学术练习,而不是Stack Overflow的主题。
答案 1 :(得分:1)
我没有收到该错误消息。我的秘密?单引号:
/bin/sh -c '/bin/true $(seq 1 100000)'
如果我使用双引号,我会在每个shell中得到错误:
$ /bin/sh -c "/bin/true $(seq 1 100000)"
-bash: /bin/sh: Argument list too long
$ /bin/bash -c "/bin/true $(seq 1 100000)"
-bash: /bin/bash: Argument list too long
$ /bin/ksh -c "/bin/true $(seq 1 100000)"
-bash: /bin/ksh: Argument list too long
$ /bin/zsh -c "/bin/true $(seq 1 100000)"
-bash: /bin/zsh: Argument list too long
当使用双引号时,参数列表在当前shell中展开,因为Bash是发出错误“-bash:...”的事实,无论用于运行命令的shell是什么。顺便说一下,我的系统sh
是Dash。
即使对于其他“主机”外壳也是如此:
$ dash
$ /bin/bash -c '/bin/true $(seq 1 100000)'
$ /bin/bash -c "/bin/true $(seq 1 100000)"
dash: /bin/bash: Argument list too long
病人:医生,我这样做会很疼。“
医生:不要这样做。
答案 2 :(得分:0)
减少100,000,直到您不再收到错误
/bin/sh -c "/bin/true $(seq 1 99999)"
/bin/sh -c "/bin/true $(seq 1 99998)"
等
答案 3 :(得分:0)
创建一个文件,#!/bin/sh
作为第一行,然后将命令的其余部分放在后续行中? :)
更严重的是,您还可以使用-s
选项从STDIN读取命令,这样您就可以生成长命令行并将其输入/bin/sh -s
答案 4 :(得分:0)
在我的操作系统上,它是通过二分法获得的最大长度
/bin/sh -c "/bin/true $(perl -e 'print"a"x131061')"
所以它给了131071
但是没有理由拥有一条线;如果是由于大量的参数,可以使用“$ @”代替;例如
/bin/sh -c 'command "$@"' -- arg1 arg2 .. argn