xargs 的不规则参数计数

tom*_*asz 2 bash xargs perl

为什么数字如此不规则?

echo {1..200000} | xargs perl -E 'say "ok:", scalar @ARGV'
ok:23691
ok:21840
ok:21840
ok:21840
ok:20261
ok:18720
ok:18720
ok:18720
ok:18720
ok:15648
Run Code Online (Sandbox Code Playgroud)

标准参数长度更文明。

perl -E' say "1 " x 900000' | xargs perl -E 'say "ok:", scalar @ARGV'
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:48240
Run Code Online (Sandbox Code Playgroud)

关键因素是什么?

ilk*_*chu 6

重要的数字是(所有)参数的总长度,以及 xargs 决定使用的命令缓冲区大小。

第一个取决于您运行的命令的固定命令行,参数 xargs 给出每次调用。perl -E 'say "ok:", scalar @ARGV'是 32 字节,计算终止字符串的 NUL 字节(即perl<NUL>-E<NUL>say "ok:", scalar @ARGV<NUL>。在第二个示例中,所有参数都是两个字节,1<NUL>因此 32 + 65520 * 2 字节,或 131072 B = 128 * 1024 B = 128 kB。

显然在第一个例子中,参数的长度不同,给出不同的计数,但逻辑应该是相同的。例如,第二到第四次运行的 21840 args 匹配 5 位参数(每个 6 字节):21840 * 6 + 32 = 131072。

命令缓冲区的大小可能取决于实现,但 GNU xargs 可以用 显示它xargs --show-limits,在我的 Linux 上,我得到:

$ echo | xargs --show-limits
Your environment variables take up 2305 bytes
POSIX upper limit on argument length (this system): 2092799
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2090494
Size of command buffer we are actually using: 131072
Maximum parallelism (--max-procs must be no greater): 2147483647
Run Code Online (Sandbox Code Playgroud)

查看倒数第二行,这是完全相同的数字。

您可以更改它使用的缓冲区的大小-s,例如仅使用 10 kB 缓冲区:

$ perl -E' say "1 " x 90000' | xargs -s 10240 perl -E 'say "ok:", scalar @ARGV' 
ok:5104
ok:5104
ok:5104
...
Run Code Online (Sandbox Code Playgroud)

当然还有-n限制单个参数的数量:

$ echo {1..200000} | xargs -n 10000 perl -E 'say "ok:", scalar @ARGV' 
ok:10000
ok:10000
ok:10000
...
Run Code Online (Sandbox Code Playgroud)

--show-limits 提到环境变量,因为它们与命令行参数使用相同的空间,如果您将缓冲区大小提高到足够接近系统最大值,它们的大小也开始重要。

我不确定系统是否还会根据限制计算指向参数字符串的指针的大小,但至少 xargs 似乎并不关心这一点。