“参数列表太长”:如何在不更改命令的情况下处理它?


18

当我运行类似的命令时ls */*/*/*/*.jpg,出现错误

-bash: /bin/ls: Argument list too long

我知道为什么会这样:这是因为对命令参数的空间大小存在内核限制。标准建议是更改我使用的命令,以避免为参数(例如use findxargs)占用太多空间。

如果我不想更改命令怎么办?如果我想继续使用相同的命令怎么办?我如何才能使事情“正常运行”,而不会出现此错误?有哪些解决方案?


有用的阅读:Bash FAQ 95。在不更改命令的情况下,除了重新编译以增加参数列表的最大大小或更改目录结构以减少文件之外,您无能为力。
2012年

1
基于Linux内核版本的@ jw013可能会增加参数列表- 有关最新系统更改的详细信息,请参见unix.stackexchange.com/a/45161/8979
Ulrich Dangel,2012年

@UlrichDangel,是的,有可能!看我的回答;我的答案显示了如何做到这一点(在Linux上,具有足够的内核)。
DW 2012年

Answers:


26

在Linux上,命令参数的最大空间量为可用堆栈空间量的1/4。因此,一种解决方案是增加可用于堆栈的空间量。

短版:运行类似

ulimit -s 65536

较长的版本:堆栈的默认可用空间约为8192 KB。您可以看到可用空间量,如下所示:

$ ulimit -s
8192

选择一个较大的数字,然后设置可用于堆栈的空间量。例如,如果您想尝试允许最多65536 KB的堆栈,请运行以下命令:

$ ulimit -s 65536

您可能需要使用试错法来尝试将其设置为多大。在许多情况下,这是一个快速和肮脏的解决方案,消除了需要修改指令,并制定出的语法findxargs等(虽然我知道有这样做其他福利)。

我相信这是特定于Linux的。我怀疑它可能在其他任何Unix操作系统(未经测试)上都无济于事。


1
您可以像这样验证它是否有效:$ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
Alex

2

这篇Linux Journal文章提供了4种解决方案。仅第四个解决方案不涉及更改命令:

方法4涉及手动增加内核中为命令行参数分配的页面数。如果查看include / linux / binfmts.h文件,则会在顶部附近找到以下内容:

/*
 * MAX_ARG_PAGES defines the number of pages allocated for   arguments
 * and envelope for the new program. 32 should suffice, this gives
 * a maximum env+arg of 128kB w/4KB pages!
 */
#define MAX_ARG_PAGES 32

为了增加专用于命令行参数的内存量,您只需要为MAX_ARG_PAGES值提供更大的数字即可。保存此编辑后,只需像通常一样重新编译,安装并重新引导到新内核中即可。

在我自己的测试系统上,我设法将该值提高到64,从而解决了所有问题。经过广泛的测试,自切换以来,我再也没有遇到过一个问题。这是完全可以预期的,因为即使将其MAX_ARG_PAGES设置为64,我可能产生的最长的命令行也只能占用256KB的系统内存-按照当今的系统硬件标准,这并不是很多。

方法4的优点很明显。现在,您可以像往常一样简单地运行命令,并且该命令成功完成。缺点也很明显。如果将命令行可用的内存量增加到系统可用内存量之外,则可以在自己的系统上创建DOS攻击并使它崩溃。特别是在多用户系统上,即使很小的增长也会产生重大影响,因为随后会为每个用户分配额外的内存。因此,请始终在您自己的环境中进行广泛的测试,因为这是确定方法4对您而言是否可行的最安全方法。

我同意这种限制是非常令人讨厌的。


1

代替ls */*/*/*/*.jpg,尝试:

echo */*/*/*/*.jpg | xargs ls

xargs(1)知道系统上的最大参数数目,并且将中断其标准输入以多次调用指定的命令行,而无论该参数是多少(不超过该限制)(您也可以将其设置为小于使用-n选项将操作系统的最大容量)。

例如,假设限制为3个参数,并且您有五个文件。在这种情况下,xargs将执行ls两次:

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

通常这是非常合适的,但并非总是如此-例如,您不能依靠ls(1)为您正确地所有条目进行排序,因为每个单独的ls调用都只会对赋予它的条目的子集进行排序xargs

尽管您可以按照其他人的建议突破限制,但仍然会有限制-某天您的JPG集合将再次超出限制。您应该准备脚本以处理无限数量...


谢谢你的主意!这不是一个坏的解决方法。两个警告:1.这打破了名称中带有空格的目录和文件名,因此它不是一个完美的替代品。2. 在不是Shell内置命令的shell 上,使用Argument list too long,而echo不是使用会遇到同样的问题吗?(也许在大多数shell中这不是问题,所以也许无关紧要。)lsecho
DW

1
是的,文件名中的特殊字符是一个问题。最好的选择是find-print0谓词一起使用-并将其输出传递给xargswith -0选项。 echo是内置的Shell,不受exec(3)命令行限制。
Mikhail T.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.