Miałem wrażenie, że maksymalna długość pojedynczego argumentu nie była tutaj problemem, tyle że całkowity rozmiar ogólnej tablicy argumentów plus rozmiar środowiska, który jest ograniczony ARG_MAX
. Pomyślałem więc, że coś takiego się powiedzie:
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
Ponieważ - 100
jest to więcej niż wystarczające, aby uwzględnić różnicę między rozmiarem środowiska w powłoce a echo
procesem. Zamiast tego dostałem błąd:
bash: /bin/echo: Argument list too long
Po dłuższej zabawie odkryłem, że maksimum to pełny rząd heksów wielkości mniejszy:
/bin/echo \
$(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) \
>/dev/null
Gdy jeden minus zostanie usunięty, błąd powraca. Pozornie maksimum dla pojedynczego argumentu jest w rzeczywistości, ARG_MAX/16
a -1
konta dla bajtu zerowego są umieszczane na końcu ciągu w tablicy argumentów.
Inną kwestią jest to, że gdy argument się powtarza, całkowity rozmiar tablicy argumentów może być bliższy ARG_MAX
, ale wciąż nie do końca:
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
Użycie "${args[0]:6533}"
tutaj powoduje wydłużenie ostatniego argumentu o 1 bajt i powoduje Argument list too long
błąd. Ta różnica prawdopodobnie nie zostanie uwzględniona w zależności od wielkości środowiska:
$ cat /proc/$$/environ | wc -c
1045
Pytania:
- Czy to jest poprawne zachowanie, czy może gdzieś jest błąd?
- Jeśli nie, czy takie zachowanie jest gdziekolwiek udokumentowane? Czy istnieje inny parametr, który określa maksimum dla pojedynczego argumentu?
- Czy to zachowanie jest ograniczone do Linuksa (czy nawet niektórych jego wersji)?
- Co odpowiada dodatkowej rozbieżności ~ 5 KB między faktycznym maksymalnym rozmiarem tablicy argumentów oraz przybliżonym rozmiarem środowiska i
ARG_MAX
?
Dodatkowe informacje:
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
zależy od prądu ulimit -s
. Ustaw na nieograniczony i uzyskaj niesamowite 4611686018427387903 dla ARG_MAX.