ZSH 中任何命令的“参数列表太长”

ZSH 中任何命令的“参数列表太长”

我希望我的解释能够更彻底,但我已经使用相同的 Artix 设置有一段时间了,没有任何我无法自行修复的问题。但是,安装 VirtualBox 后(我认为与此问题无关),重新启动后我突然无法在终端中执行任何命令。无论有多少参数,或者有多少参数,我的 zsh 都会回复参数列表太长。从执行 dwm 到使用 ls,所有事情都会发生这种情况。我尝试将 .zshrc 擦除到最低限度,但无论我尝试什么都不起作用。不过 Bash 和 shell 确实可以工作。有任何想法吗?

答案1

参数列表太长是通常对应于 E2BIG 错误代码的错误消息:

$ zmodload zsh/system
$ syserror E2BIG
Argument list too long

execve()E2BIG 是当要求执行参数列表和环境变量字符串大于支持的命令时返回的错误代码,或者在 Linux 上当单个参数或环境字符串大于 128KiB 时返回的错误代码。

总体限制以及具体如何尺寸计算取决于系统。在现代版本的 Linux 中,它源自堆栈大小的当前限制。您可以通过以下方式获取它getconf ARG_MAX(假设您可以执行getconf):

$ getconf ARG_MAX
2097152
$ limit stacksize 1024 # KiB, so 1MiB
$ getconf ARG_MAX
262144

这是堆栈大小限制的四分之一,尽管它至少为 128KiB(如果将堆栈大小限制降得太低,您将开始遇到各种其他问题)。

在这里,由于每个命令都会出现错误,包括那些参数列表较小的命令,因此我们可以合理地假设已达到该限制,因为您有一个非常大的环境变量,或者环境变量及其累积大小传递给的值被处决命令大于 ARG_MAX。

例如,如果您allexport错误地设置了 POSIX 选项,导致所有 shell 变量都被放入环境中,并且定义了很多变量(可能是通过运行不同的完成函数,其中一些变量),则可能会发生这种情况缓存变量中的信息。

检查:

echo $options[allexport]

哪个应该报告off。如果没有,请检查设置该选项的启动文件。可以是set -a, set -o allexport, setopt allexport, options[allexport]=on, 或该选项的各种可能的拼写(大小写和下划线被忽略,所以它也可以是setopt ALL_EXPORT例如)。

您可以尝试其他一些方法:

检查堆栈大小的当前限制:

$ limit stacksize
stacksize       8MB

检查ARG_MAX的当前值:

$ (typeset +x -m '*'; getconf ARG_MAX)
2097152

typeset +x -m '*'删除环境的所有变量。这包括$PATH,但你的系统应该仍然能够getconf在默认情况下找到$PATH

检查环境大小:

$ typeset -x | wc -c
4395

(这是一个近似值,不包括未映射到 shell 变量的变量,计数可能包括添加的一些引号字符,typeset -x这些字符不在变量的值中,并且它没有考虑到您还需要计算指向这些环境字符串的指针列表的大小)。

查找大小大于 128KiB 的环境变量:

$ LC_ALL=C
$ export test=${(l[132000])}
$ for v (${(k)parameters[(R)*export*]}) {(( (l=${(P)#v}) >= 131071 )) && echo "$v: $l"}
test: 132000
$ ls
ls:2: argument list too long: ls

root从不受该问题影响的单独运行的 shell 中,您还可以运行:

strace -s150000 -vfe execve -p "$pid"

$pid存在该问题的 shell 的进程 ID 在哪里(请参阅 的输出echo $$),然后尝试在该 shell 中运行命令。

strace应该向您显示execve()正在执行且失败的确切系统调用,E2BIG以及参数和环境字符串的完整列表(每个被截断为 150000 字节),这有望帮助您识别问题。

相关内容