Вопрос или проблема
Я хотел бы более подробно объяснить, но я использую свою настройку Artix уже некоторое время, и не сталкивался с проблемами, которые не мог бы решить сам. Однако после установки VirtualBox (что, я думаю, не связано с этой проблемой) я внезапно не могу выполнить никакую команду в терминале после перезагрузки. Неважно, сколько аргументов, или даже если их нет вовсе, мой zsh отвечает: Argument list too long. Это происходит со всем, от выполнения dwm до использования ls. Я пытался очистить мой .zshrc до минимума, и что бы я ни пробовал, ничего не работает. Однако Bash и shell работают. Какие-нибудь идеи?
Argument list too long – это сообщение об ошибке, которое обычно соответствует коду ошибки E2BIG:
$ zmodload zsh/system
$ syserror E2BIG
Argument list too long
E2BIG – это код ошибки, возвращаемый execve()
при попытке выполнить команду со списком аргументов и строками переменных окружения, которые больше, чем поддерживается, или в Linux, когда один аргумент или строка окружения больше, чем 128KiB.
Общий лимит и то, как именно он вычисляется, зависят от системы. В современных версиях Linux он определяется от текущего лимита размера стека. Вы можете получить его с помощью команды getconf ARG_MAX
(если вы можете выполнить getconf
):
$ getconf ARG_MAX
2097152
$ limit stacksize 1024 # KiB, то есть 1MiB
$ getconf ARG_MAX
262144
Это четверть лимита на размер стека, хотя он составляет по крайней мере 128KiB (и если вы установите лимит на размер стека слишком низким, у вас начнутся другие проблемы).
Здесь, поскольку вы получаете ошибку для каждой команды, включая те, у которых небольшой список аргументов, мы можем обоснованно предположить, что этот лимит достигнут, потому что у вас либо очень большая переменная окружения, либо суммарный размер переменных окружения и их значений, передаваемых выполненной команде, больше, чем ARG_MAX.
Это могло случиться, например, если вы случайно установили POSIX-опцию allexport
, что приводит к тому, что все переменные оболочки помещаются в окружение, и у вас определено много переменных, возможно, через выполнение различных функций завершения, некоторые из которых кэшируют информацию в переменных.
Проверьте с помощью:
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
(это приблизительная оценка, которая не включает переменные, не привязанные к переменным оболочки, и в счет могут быть включены некоторые символы экранирования, добавленные 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
, которая не подвержена этой проблеме, вы также можете выполнить:
strace -s150000 -vfe execve -p "$pid"
Где $pid
– идентификатор процесса вашей оболочки, у которой такая проблема (см. вывод echo $$
), а затем попробуйте выполнить команду в этой оболочке.
strace
должен показать вам точный системный вызов execve()
, который выполняется и который завершился с ошибкой E2BIG
вместе с полным списком аргументов и строк окружения (усеченным до 150000 байт), что, надеюсь, поможет вам определить проблему.
Я получил эту ошибку, потому что у меня было слишком много всего в автоматически сгенерированном файле .env.
Я получил эту ошибку, потому что мой параметр оболочки path
был очень длинным и содержал множество дублирующихся записей. Я выяснил это, запустив команду export
, которая показала чрезвычайно длинный path
. Причина, по которой мой path
был таким длинным, заключалась в том, что я неправильно добавлял каталоги в мой .zshrc файл, используя path+=('/path/to/directory' $path)
вместо просто path+=('/path/to/directory')
.
Ответ или решение
Ошибка "Argument list too long" в ZSH может быть достаточно раздражающей и зачастую указывает на проблемы с объемом передаваемых аргументов или средой выполнения командной оболочки. В данном случае, данная ошибка вероятно может быть вызвана превышением лимита на длину списка аргументов или переменных среды. Исследуем возможные причины и решения этой проблемы с точки зрения теории, примеров и практического применения.
Теория
Проблема "Argument list too long" обычно связана с системным ограничением на количество и размер аргументов и переменных окружения при выполнении команд через системные вызовы, такие как execve()
. Этот вызов возвращает ошибку E2BIG, когда список аргументов или строк переменных превышает допустимый лимит.
На современных системах Linux максимальный размер вычисляется из текущей установки размера стека процесса и может быть получен с помощью команды getconf ARG_MAX
. На разных системах это значение может варьироваться, но обычно составляет несколько мегабайт. Кроме того, стоит отметить, что отдельная строка аргумента или переменной не может превышать 128 килобайт. Это может быть причиной ошибки, если переменные или аргументы имеют большой размер.
Примеры
В данном случае, даже запуск простых команд, таких как ls
или dwm
, вызывает ошибку, что говорит о вероятности наличия больших или неправильно настроенных переменных окружения. Одной из возможных причин может быть активация опции allexport
, что приводит к экспорту всех переменных, включая временные и кэшированные данные, используемые только внутри вашей настройки ZSH. Это может существенно увеличить размер передаваемых данных.
Пример неправильной настройки может выглядеть так:
setopt allexport
или
path+=('/some/path' $path)
Эти настройки могут вызвать дублирование путей в переменной PATH
, либо экспоненциальный рост количества переменных окружения.
Применение
Вот шаги, которые следует предпринять для устранения и предотвращения проблемы "Argument list too long":
-
Проверка опции allexport:
Выполните команду:echo $options[allexport]
Она должна вернуть
off
. Если не так, проверьте ваши загрузочные файлы на предмет использованиюset -a
,set -o allexport
или других форм этого параметра и отключите его, если он не требуется. -
Анализ списка переменных окружения:
Убедитесь, что в переменнойPATH
и других переменных нет ненужных и дублирующих значений:typeset -x | wc -c
Это даст примерное представление о размере использованных переменных.
-
Исключение чрезмерно длинных переменных:
Используйте следующие команды для определения очень больших переменных:LC_ALL=C for v (${(k)parameters[(R)*export*]}); do (( (l=${(P)#v}) >= 131071 )) && echo "$v: $l"; done
-
Использование strace для диагностики:
Если ни один из вышеописанных шагов не помогает, используйтеstrace
для более детальной диагностики:strace -s150000 -vfe execve -p "$(pgrep -u $USER zsh)"
Это поможет выявить конкретные вызовы
execve()
, которые вызывают ошибку. -
Редактирование .zshrc:
Убедитесь, что в вашем.zshrc
нет дублирования путей:path+=('/путь/до/папки')
Избегайте добавления
$path
в конце выражения, если оно не требуется.
Следуя этим шагам, вы сможете проанализировать и устранить причины возникновения ошибки "Argument list too long" в ZSH и обеспечить стабильность работы вашей оболочки в дальнейшем.