Tôi có ấn tượng rằng độ dài tối đa của một đối số không phải là vấn đề ở đây nhiều như tổng kích thước của mảng đối số tổng thể cộng với kích thước của môi trường, được giới hạn ARG_MAX
. Vì vậy, tôi nghĩ rằng một cái gì đó như sau sẽ thành công:
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
Với sự - 100
tồn tại quá đủ để tính đến sự khác biệt giữa kích thước của môi trường trong vỏ và echo
quy trình. Thay vào đó tôi đã nhận được lỗi:
bash: /bin/echo: Argument list too long
Sau khi chơi một lúc, tôi thấy rằng mức tối đa là một thứ tự hex có độ lớn nhỏ hơn:
/bin/echo \
$(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) \
>/dev/null
Khi trừ đi một cái, lỗi sẽ trả về. Dường như mức tối đa cho một đối số là thực sự ARG_MAX/16
và các -1
tài khoản cho byte null được đặt ở cuối chuỗi trong mảng đối số.
Một vấn đề khác là khi đối số được lặp lại, tổng kích thước của mảng đối số có thể gần hơn ARG_MAX
, nhưng vẫn không hoàn toàn ở đó:
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
Sử dụng "${args[0]:6533}"
ở đây làm cho đối số cuối cùng dài hơn 1 byte và đưa ra Argument list too long
lỗi. Sự khác biệt này khó có thể được tính bằng kích thước của môi trường được đưa ra:
$ cat /proc/$$/environ | wc -c
1045
Câu hỏi:
- Đây có phải là hành vi chính xác, hoặc có một lỗi ở đâu đó?
- Nếu không, hành vi này được ghi nhận ở bất cứ đâu? Có một tham số khác xác định mức tối đa cho một đối số không?
- Là hành vi này giới hạn trong Linux (hoặc thậm chí các phiên bản cụ thể như vậy)?
- Điều gì chiếm sự khác biệt ~ 5KB bổ sung giữa kích thước tối đa thực tế của mảng đối số cộng với kích thước gần đúng của môi trường và
ARG_MAX
?
Thông tin bổ sung:
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
phụ thuộc vào hiện tại ulimit -s
. Đặt nó thành không giới hạn và nhận được 4611686018427387903 tuyệt vời cho ARG_MAX.