29

一个命令行可以传递多长时间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 的解释。

4

4 回答 4

27

TL;博士

单个参数必须短于 MAX_ARG_STRLEN。

分析

根据此链接

作为自 2.6.23 起的附加限制,一个参数不得长于 MAX_ARG_STRLEN (131072)。如果您生成像“sh -c 'generated with long arguments'”这样的长调用,这可能会变得相关。

这正是 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

工作得很好。它肯定会很慢,因为您在每次通过循环时都会产生一个进程,但它肯定会绕过您遇到的命令行限制。

描述你真正的问题

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

于 2012-07-13T17:52:26.607 回答
4

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

/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

病人:医生,我这样做会很痛。”
医生:不要那样做。

于 2012-07-13T18:48:55.577 回答
0

创建一个文件#!/bin/sh作为第一行,然后将其余的命令放在后续行中?:)

更严重的是,您还可以使用该-s选项从 STDIN 读取命令,因此您可以生成长命令行并将其输入到/bin/sh -s

于 2012-07-13T17:46:18.817 回答
0

在我的操作系统上,它是二分法获得的最大长度

/bin/sh -c "/bin/true $(perl -e 'print"a"x131061')"

所以它给出了 131071

但是没有理由排那么长;如果是因为参数太多,可以用“$@”代替;例如

/bin/sh -c 'command "$@"' -- arg1 arg2 .. argn
于 2012-07-13T18:27:44.540 回答