Ограничение "слишком много аргументов" применяется к встроенным оболочкам?
Я просмотрел много сообщений о переполнении стека, а также несколько связанных сообществ в отношении темы argument list too long
, и я, похоже, не вижу четких цифр, если ограничение длины применяется к встроенным оболочкам или нет.
Скажем, я хочу передать очень длинную строку в команду через стандартный ввод:
string="a very long list of words ..."
Могу ли я сказать:
# not using double quotes around $string is deliberate
printf '%s\n' $string | cmd ...
или
cmd <<< $string
Или даже подключите его к xargs
:
printf '%s\n' $string | xargs cmd ...
Кто-нибудь может прояснить это?
Ответы
Ответ 1
В bash принудительное ограничение OS на длину командной строки, вызывающее ошибку argument list too long
, не применяется к встроенным оболочкам.
Эта ошибка срабатывает, когда syscall execve()
возвращает код ошибки E2BIG
. При вызове встроенного вызова не задействован вызов execve()
, поэтому ошибка не может быть выполнена.
Таким образом, обе предлагаемые вами операции безопасны: cmd <<< "$string"
записывает $string
во временный файл, который не требует, чтобы он передавался как элемент argv (или переменная среды, которая хранится в том же пуле зарезервированного пространства); и printf '%s\n' "$cmd"
выполняется внутренне для оболочки, если только конфигурация оболочки не была изменена, как и при использовании enable -n printf
, для использования внешней реализации printf
.
Ответ 2
Кажется, мне кажется, что ограничение длины применяется к встроенным командам оболочки.
Возможно, нет, но вы должны проверить исходный код вашей конкретной версии bash
(поскольку это бесплатное программное обеспечение). Тем не менее, очевидно, существует какое-то более серьезное ограничение (в частности, из-за того, что некоторая malloc
, выполненная внутри bash
, может выйти из строя), но затем вы получите другое сообщение об ошибке или поведение.
AFAIK, слишком длинная ошибка списка аргументов дается execve (2) с ошибкой E2BIG
и встроенными функциями bash не fork
, а затем execve
(например, для вызова внешних программ).
На практике E2BIG
может появляться с несколькими сотнями тысяч байтов (точное ограничение зависит от ядра и системы), но я думаю, что встроенные функции могут использоваться на нескольких десятках мегабайт (на сегодняшних десктопах). Но YMMV (поскольку вы можете использовать ulimit
, чтобы ваша оболочка выполняла setrlimit (2)...). Я не буду рекомендовать обработку гигабайт данных через встроенные оболочки.
BTW, xargs (1) может оказаться полезным, и вы даже можете поднять лимит (для E2BIG
), перекомпилировав свое ядро (а также некоторыми другими способами, в последних ядрах). Несколько лет назад это была сильная мотивация для меня перекомпилировать ядра.