У мене було враження, що максимальна довжина одного аргументу тут не є проблемою настільки, як загальний розмір загального масиву аргументів плюс розмір середовища, який обмежений ARG_MAX
. Таким чином, я думав, що щось подібне вдасться:
env_size=$(cat /proc/$$/environ | wc -c)
(( arg_size = $(getconf ARG_MAX) - $env_size - 100 ))
/bin/echo $(tr -dc [:alnum:] </dev/urandom | head -c $arg_size) >/dev/null
Маючи це - 100
більше, ніж достатньо, щоб врахувати різницю між розмірами середовища в оболонці та echo
процесом. Натомість я отримав помилку:
bash: /bin/echo: Argument list too long
Погравши деякий час, я виявив, що максимум - це повна шістнадцятковий порядок менше:
/bin/echo \
$(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) \
>/dev/null
Коли мінус один видаляється, помилка повертається. Мабуть, максимум для одного аргументу є насправді, ARG_MAX/16
а -1
рахунки для нульового байту розміщуються в кінці рядка в масиві аргументів.
Інша проблема полягає в тому, що коли аргумент повторюється, загальний розмір масиву аргументів може бути ближчим ARG_MAX
, але все ще не зовсім таким:
args=( $(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) )
for x in {1..14}; do
args+=( ${args[0]} )
done
/bin/echo "${args[@]}" "${args[0]:6534}" >/dev/null
Використання "${args[0]:6533}"
тут робить останній аргумент на 1 байт довшим і видає Argument list too long
помилку. Цю різницю навряд чи можна врахувати за розміром даного середовища:
$ cat /proc/$$/environ | wc -c
1045
Запитання:
- Це правильна поведінка, чи є помилка десь?
- Якщо ні, то чи є така поведінка десь задокументована? Чи є інший параметр, який визначає максимум для одного аргументу?
- Чи обмежується така поведінка лише Linux (або навіть певними версіями такої версії)?
- Що пояснює додаткову ~ 5 КБ розбіжність між фактичним максимальним розміром масиву аргументу плюс приблизним розміром середовища та
ARG_MAX
?
Додаткова інформація:
uname -a
Linux graeme-rock 3.13-1-amd64 #1 SMP Debian 3.13.5-1 (2014-03-04) x86_64 GNU/Linux
getconf ARG_MAX
залежить від струму ulimit -s
. Встановіть його необмежену кількість і отримайте дивовижні 4611686018427387903 для ARG_MAX.