«Слишком длинный список аргументов» в ZSH с любой командой

Следующее должно работать вsh:

"$@" 2>&1 | while read line ; do echo -e "r2g: $line" ; done

Обратите внимание, что поведение echo -eможет отличаться в sh (, например. на самом деле он может вывести -e r2g:....)

1
28.08.2020, 19:06
1 ответ

Слишком длинный список аргументов — это сообщение об ошибке, которое обычно соответствует коду ошибки E2BIG :

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

E2BIG — это код ошибки, возвращаемый execve()при запросе на выполнение команды со списком аргументов и строк переменных среды, превышающих поддерживаемые, или в Linux, когда размер одного аргумента или строки переменных среды превышает 128 КБ.

Общий предел и способ расчета размера зависят от системы. В современных версиях Linux это производное от текущего ограничения размера стека. Вы можете получить его с помощью getconf ARG_MAX(, если вы можете выполнитьgetconf):

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

Это четверть ограничения на размер стека, хотя он составляет не менее 128 КБ (, и если вы уменьшите ограничение на размер стека слишком низко, вы начнете сталкиваться со всевозможными другими проблемами ).

Здесь, поскольку вы получаете сообщение об ошибке для каждой команды, в том числе с небольшим списком аргументов, мы можем разумно предположить, что этот предел достигнут, потому что либо у вас очень большая переменная среды, либо совокупный размер среды переменных и их значений, переданных в выполненных команд больше, чем 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 _МАКС.:

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

typeset +x -m '*'удаляет все переменные среды. Это включает в себя $PATH, но ваша система все равно сможет найти getconfв $PATHпо умолчанию.

Проверьте размер окружения:

$ typeset -x | wc -c
4395

(это приближение, которое не включает переменные, которые не сопоставлены с переменными оболочки, подсчет может включать некоторые символы кавычек, добавленные typeset -x, которых нет в значениях переменных, и он не учитывает учтите тот факт, что вам также необходимо подсчитать размер списка указателей на эти строки env ).

Ищите переменные среды, размер которых превышает 128 КБ:

$ 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, а также полный список аргументов и строк окружения (, усеченных до 150 000 байт каждый ), что, надеюсь, должно помогите определить проблему.

2
18.03.2021, 23:09

Теги

Похожие вопросы