D.W*_*.W. 35 command-line kernel xargs
当我运行类似的命令时ls */*/*/*/*.jpg,出现错误
-bash: /bin/ls: Argument list too long
Run Code Online (Sandbox Code Playgroud)
我知道为什么会发生这种情况:这是因为内核对命令参数的空间量有限制。标准建议是更改我使用的命令,以避免需要太多的参数空间(例如,使用find和xargs)。
如果我不想更改命令怎么办?如果我想继续使用相同的命令怎么办?我怎样才能让事情“正常工作”,而不会出现这个错误?有哪些解决方案?
D.W*_*.W. 47
在 Linux 上,命令参数的最大空间量是可用堆栈空间量的 1/4。因此,解决方案是增加堆栈的可用空间量。
简短版本:运行类似
ulimit -s 65536
Run Code Online (Sandbox Code Playgroud)
更长的版本:堆栈的默认可用空间量类似于 8192 KB。您可以看到可用空间量,如下所示:
$ ulimit -s
8192
Run Code Online (Sandbox Code Playgroud)
选择一个更大的数字,并设置堆栈的可用空间量。例如,如果您想尝试为堆栈最多允许 65536 KB,请运行以下命令:
$ ulimit -s 65536
Run Code Online (Sandbox Code Playgroud)
您可能需要使用试错法来处理需要多大的尺寸。在许多情况下,这是一个快速和肮脏的解决方案,消除了需要修改指令,并制定出的语法find,xargs等(虽然我知道有这样做其他福利)。
我相信这是 Linux 特有的。我怀疑它在任何其他 Unix 操作系统(未经测试)上可能都无济于事。
这篇Linux Journal 文章给出了 4 个解决方案。只有第四种解决方案不涉及更改命令:
方法 #4 涉及手动增加内核中为命令行参数分配的页数。如果您查看 include/linux/binfmts.h 文件,您会在顶部附近发现以下内容:
Run Code Online (Sandbox Code Playgroud)/* * 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
Run Code Online (Sandbox Code Playgroud)
xargs(1) 知道系统上的最大参数数是多少,并且会分解其标准输入以多次调用指定的命令行,参数不超过该限制,无论是什么(您也可以将其设置得更低)比使用该-n选项的操作系统的最大值)。
例如,假设限制为 3 个参数并且您有五个文件。在这种情况下xargs将执行ls两次:
ls 1.jpg 2.jpg 3.jpgls 4.jpg 5.jpg通常这非常合适,但并非总是如此——例如,您不能依赖ls(1)为您正确排序所有条目,因为每个单独的ls-invocation 只会对由xargs.
尽管您可以按照其他人的建议突破限制,但仍然存在限制——总有一天您的 JPG 收藏将再次超出限制。你应该准备你的脚本来处理无限的数字......