“参数列表太长”限制是否适用于shell buildins?

我浏览了很多关于StackOverflow的post以及一些相关的社区,关于argument list too long话题,我似乎没有清楚地指出长度限制是否适用于shell buildins。

比方说,我有一个很长的string,我想通过标准input传递给一个命令:

 string="a very log list ..." 

我能说……么:

 # not using double quotes around $string is deliberate printf '%s\n' $string | cmd ... 

要么

 cmd <<< $string 

甚至xargsxargs

 printf '%s\n' $string | xargs cmd ... 

有人可以澄清这一点?

在bash中,操作系统对导致错误argument list too long命令行长度的限制不适用于shell内建argument list too long

execve()系统调用返回错误码E2BIG时,会触发此错误。 调用内置函数时不涉及execve()调用,所以错误不能发生。

因此,你提出的两个操作都是安全的: cmd <<< "$string"$string写入一个临时文件,它不要求它作为一个argv元素传递(或者是一个环境变量,预留空间池); 和printf '%s\n' "$cmd"发生在shell的内部,除非已经修改了shell的配置,像enable -n printf ,使用一个外部的printf实现。

我似乎并不认为如果长度限制适用于壳建筑或不。

可能不是,但你应该检查你的特定版本的bash的源代码(因为它是自由软件)。 然而,显然有一些更大的限制(特别是因为在bash完成的一些malloc可能会失败),但是会得到另一个错误信息或行为。

AFAIK,参数列表太长错误是由execve(2)与E2BIG失败给出的,并且bash的内建函数不fork然后execve (如调用外部程序那样的命令)。

在实践中, E2BIG可能会出现几十万字节(确切的限制取决于内核和系统),但是我猜这些内建函数可能在几十兆字节(在今天的桌面上)上使用。 但YMMV(因为你可以使用ulimit让你的shell做一些setrlimit(2) …)。 我不建议通过shell内建处理千兆字节的数据。

顺便说一句, xargs(1)可以是有帮助的,你甚至可以通过重新编译你的内核(也可以通过其他方式,在最近的内核中)来提高E2BIG的限制。 几年前,这是我重新编译内核的强烈动机。