Ограничение "слишком много аргументов" применяется к встроенным оболочкам?

Я просмотрел много сообщений о переполнении стека, а также несколько связанных сообществ в отношении темы 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), перекомпилировав свое ядро (а также некоторыми другими способами, в последних ядрах). Несколько лет назад это была сильная мотивация для меня перекомпилировать ядра.