当我运行类似的命令时ls */*/*/*/*.jpg
,出现错误
-bash: /bin/ls: Argument list too long
我知道为什么会这样:这是因为对命令参数的空间大小存在内核限制。标准建议是更改我使用的命令,以避免为参数(例如use find
和xargs
)占用太多空间。
如果我不想更改命令怎么办?如果我想继续使用相同的命令怎么办?我如何才能使事情“正常运行”,而不会出现此错误?有哪些解决方案?
当我运行类似的命令时ls */*/*/*/*.jpg
,出现错误
-bash: /bin/ls: Argument list too long
我知道为什么会这样:这是因为对命令参数的空间大小存在内核限制。标准建议是更改我使用的命令,以避免为参数(例如use find
和xargs
)占用太多空间。
如果我不想更改命令怎么办?如果我想继续使用相同的命令怎么办?我如何才能使事情“正常运行”,而不会出现此错误?有哪些解决方案?
Answers:
在Linux上,命令参数的最大空间量为可用堆栈空间量的1/4。因此,一种解决方案是增加可用于堆栈的空间量。
短版:运行类似
ulimit -s 65536
较长的版本:堆栈的默认可用空间约为8192 KB。您可以看到可用空间量,如下所示:
$ ulimit -s
8192
选择一个较大的数字,然后设置可用于堆栈的空间量。例如,如果您想尝试允许最多65536 KB的堆栈,请运行以下命令:
$ ulimit -s 65536
您可能需要使用试错法来尝试将其设置为多大。在许多情况下,这是一个快速和肮脏的解决方案,消除了需要修改指令,并制定出的语法find
,xargs
等(虽然我知道有这样做其他福利)。
我相信这是特定于Linux的。我怀疑它可能在其他任何Unix操作系统(未经测试)上都无济于事。
这篇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对您而言是否可行的最安全方法。
我同意这种限制是非常令人讨厌的。
代替ls */*/*/*/*.jpg
,尝试:
echo */*/*/*/*.jpg | xargs ls
xargs
(1)知道系统上的最大参数数目,并且将中断其标准输入以多次调用指定的命令行,而无论该参数是多少(不超过该限制)(您也可以将其设置为小于使用-n
选项将操作系统的最大容量)。
例如,假设限制为3个参数,并且您有五个文件。在这种情况下,xargs
将执行ls
两次:
ls 1.jpg 2.jpg 3.jpg
ls 4.jpg 5.jpg
通常这是非常合适的,但并非总是如此-例如,您不能依靠ls
(1)为您正确地对所有条目进行排序,因为每个单独的ls
调用都只会对赋予它的条目的子集进行排序xargs
。
尽管您可以按照其他人的建议突破限制,但仍然会有限制-某天您的JPG集合将再次超出限制。您应该准备脚本以处理无限数量...
Argument list too long
,而echo
不是使用会遇到同样的问题吗?(也许在大多数shell中这不是问题,所以也许无关紧要。)ls
echo
find
与-print0
谓词一起使用-并将其输出传递给xargs
with -0
选项。 echo
是内置的Shell,不受exec
(3)命令行限制。