У меня сложилось впечатление, что максимальная длина одного аргумента не была проблемой здесь, так как общий размер массива аргументов плюс размер среды, которая ограничена 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.