传递引用的参数时,为什么我会得到"/ bin/sh:参数列表太长"?

Igo*_*bin 24 bash shell command-line arguments quoting

可以传递给命令行多长时间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
Run Code Online (Sandbox Code Playgroud)

我怎么能绕过这个问题呢?

更新

我想注意到getconf这里无法帮助(因为这不是系统限制):

$ seq 1 100000 | wc -c
588895
$ getconf ARG_MAX
2097152
Run Code Online (Sandbox Code Playgroud)

更新#2

现在我明白了这里有什么意义.这不是shell限制,即系统限制,但是对于每个参数的长度,而不是整个arglist.

$ /bin/true $(seq 1 100000)
$ /bin/true "$(seq 1 100000)"
bash: /bin/true: Argument list too long
Run Code Online (Sandbox Code Playgroud)

谢谢CodeGnome的解释.

Tod*_*obs 21

TL; DR

单个参数必须短于MAX_ARG_STRLEN.

分析

根据这个链接:

作为自2.6.23以来的附加限制,一个参数不得长于MAX_ARG_STRLEN(131072).如果您生成一个长期调用,例如"使用长参数'生成的sh -c',这可能会变得相关".

这正是OP确定的"问题".虽然允许的参数数量可能非常大(请参阅参考资料getconf ARG_MAX),但当您将带引号的命令传递给/ bin/sh时,shell会将带引号的命令解释为单个字符串.在OP的示例中,这个单个字符串超出了MAX_ARG_STRLEN限制,而不是扩展参数列表的长度.

具体实施

参数限制是特定于实现的.但是,这篇Linux Journal文章提出了几种解决这些问题的方法,包括增加系统限制.这可能不直接适用于OP,但它在一般情况下仍然有用.

做点别的事

OP的问题实际上并不是一个真正的问题.问题是强加一个不能解决现实世界问题的任意约束.

通过使用循环,您可以轻松地解决这个问题.例如,使用Bash 4:

for i in {1..100000}; do /bin/sh -c "/bin/true $i"; done
Run Code Online (Sandbox Code Playgroud)

工作得很好.它肯定会很慢,因为你在每次循环中产生一个进程,但它肯定会遇到你遇到的命令行限制.

描述你的真实问题

如果循环无法解决您的问题,请更新问题以描述您实际尝试使用非常长的参数列表解决的问题.探索任意行长限制是一项学术练习,而不是Stack Overflow的主题.

  • 我在`2.6.31`的系统上没有`MAX_ARG_STRLEN` (2认同)

Pau*_*ce. 6

我没有收到该错误消息。我的秘密?单引号:

/bin/sh -c '/bin/true $(seq 1 100000)'
Run Code Online (Sandbox Code Playgroud)

如果我使用双引号,每个 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
Run Code Online (Sandbox Code Playgroud)

当使用双引号时,参数列表会在当前 shell 中扩展,事实证明,无论使用哪个 shell 来运行该命令,Bash 都会发出错误“-bash: ...”。sh顺便说一句,我的系统上有 Dash。

即使对于其他“主机”shell 也是如此:

$ dash
$ /bin/bash -c '/bin/true $(seq 1 100000)'
$ /bin/bash -c "/bin/true $(seq 1 100000)"
dash: /bin/bash: Argument list too long
Run Code Online (Sandbox Code Playgroud)

病人:医生,我这样做会很痛。”
医生:别这样做。