ここでは、単一の引数の最大長は、引数配列全体の合計サイズと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
しばらく遊んでみたところ、最大値が完全な16進数で1桁小さいことがわかりました。
/bin/echo \
$(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) \
>/dev/null
マイナス1が削除されると、エラーが返されます。単一の引数の最大値は実際にはARG_MAX/16
であり、-1
は引数配列内の文字列の末尾に配置されたnullバイトを考慮しているようです。
別の問題は、引数が繰り返されると、引数配列の合計サイズが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
ARG_MAX
の間の追加の〜5KBの不一致を説明するものは何ですか?uname -a
Linux graeme-rock 3.13-1-AMD64 #1 SMP Debian 3.13.5-1 (2014-03-04) x86_64 GNU/Linux
1つの引数の最大サイズを定義するパラメーターはMAX_ARG_STRLEN
です。 binfmts.h
のコメント以外に、このパラメーターのドキュメントはありません。
/*
* These are the maximum length and maximum number of strings passed to the
* execve() system call. MAX_ARG_STRLEN is essentially random but serves to
* prevent the kernel from being unduly impacted by misaddressed pointers.
* MAX_ARG_STRINGS is chosen to fit in a signed 32-bit integer.
*/
#define MAX_ARG_STRLEN (PAGE_SIZE * 32)
#define MAX_ARG_STRINGS 0x7FFFFFFF
示されているように、Linuxにはコマンドへの引数の数にも(非常に大きな)制限があります。
単一の引数のサイズの制限(引数と環境の全体的な制限とは異なります)は、Linuxに固有のようです。これ article は、UNIXのようなシステムでのARG_MAX
と同等の詳細な比較を提供します。 LinuxについてはMAX_ARG_STRLEN
について説明していますが、他のシステムでは同等のものについての言及はありません。
上記の記事では、MAX_ARG_STRLEN
がLinux 2.6.23で導入されたこと、およびコマンド引数の最大値に関連するその他の変更点についても説明しています(以下で説明します)。コミットのログ/差分は here にあります。
getconf ARG_MAX
の結果と引数と環境の実際の最大可能サイズとの間の追加の不一致を説明するものはまだ明確ではありません。 Stephane Chazelasの関連する回答 は、スペースの一部が各引数/環境文字列へのポインターによって占められていることを示唆しています。ただし、私自身の調査によると、これらのポインターは、呼び出しプロセスにE2BIG
エラーを返す可能性がある場合、execve
システムコールの早い段階では作成されません(ただし、各argv
文字列へのポインターは確実に後で作成されます)。
また、文字列は私が見る限りではメモリ内で連続しているため、ここで調整を行うことによるメモリギャップはありません。 does内の要素である可能性が非常に高いですが、余分なメモリを使い果たします。余分なスペースを何が使用するかを理解するには、カーネルがメモリを割り当てる方法に関するより詳細な知識が必要です(これは知っておくと役立つ知識なので、後で調査して更新します)。
Linux 2.6.23以降( this commit の結果として)、コマンド引数の最大値の処理方法が変更され、Linuxが他のUnixライクなシステムと異なっている。 MAX_ARG_STRLEN
とMAX_ARG_STRINGS
の追加に加えて、getconf ARG_MAX
の結果はスタックサイズに依存するようになり、ARG_MAX
のlimits.h
とは異なる場合があります。
通常、getconf ARG_MAX
の結果はスタックサイズの1/4
になります。スタックサイズを取得するためにbash
を使用して、ulimit
で以下を検討します。
$ echo $(( $(ulimit -s)*1024 / 4 )) # ulimit output in KiB
2097152
$ getconf ARG_MAX
2097152
ただし、上記の動作はこれによって若干変更されました commit (Linux 2.6.25-rc4〜121で追加)。 ARG_MAX
のlimits.h
がgetconf ARG_MAX
の結果のハード下限として機能するようになりました。スタックサイズの1/4
がARG_MAX
のlimits.h
より小さいようにスタックサイズが設定されている場合、limits.h
値が使用されます。
$ grep ARG_MAX /usr/include/linux/limits.h
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
$ ulimit -s 256
$ echo $(( $(ulimit -s)*1024 / 4 ))
65536
$ getconf ARG_MAX
131072
スタックサイズが可能な最小ARG_MAX
よりも小さい場合、スタックのサイズ(RLIMIT_STACK
)は、E2BIG
が返される前に引数/環境サイズの上限になることにも注意してください(ただし、getconf ARG_MAX
にはlimits.h
の値が表示されます)。
最後に注意すべきことは、カーネルがCONFIG_MMU
(メモリ管理ハードウェアのサポート)なしでビルドされている場合、ARG_MAX
のチェックが無効になっているため、制限は適用されません。ただし、MAX_ARG_STRLEN
およびMAX_ARG_STRINGS
は引き続き適用されます。
ARG_MAX
(および同等の)値の表が含まれます- http://www.in-ulm.de/~mascheck/various/argmax/MAX_ARG_STRLEN
の導入により、Automakeでsh -c
- http://www.mail-archive.com/bug-make@gnuを使用してシェルスクリプトをMakefileに埋め込むことでバグが発生したようです。 .org/msg05522.html_eglibc-2.18/NEWS
_内
_* ARG_MAX is not anymore constant on Linux. Use sysconf(_SC_ARG_MAX).
Implemented by Ulrich Drepper.
_
_eglibc-2.18/debian/patches/kfreebsd/local-sysdeps.diff
_内
_+ case _SC_ARG_MAX:
+ request[0] = CTL_KERN;
+ request[1] = KERN_ARGMAX;
+ if (__sysctl(request, 2, &value, &len, NULL, 0) == -1)
+ return ARG_MAX;
+ return (long)value;
_
_linux/include/uapi/linux/limits.h
_内
_#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
_
そして、_131072
_は$(getconf ARG_MAX)/16-1
です。おそらく0から始めるべきです。
あなたはglibcとLinuxを扱っています。 「正しい」_ARG_MAX
_値が返されるようにするには、getconfにもパッチを適用するとよいでしょう。
編集:
少し明確にするために(短いが熱い議論の後)
_ARG_MAX
_で定義されている_limits.h
_定数は、execで渡される1つの引数の最大長を示します。
_getconf ARG_MAX
_コマンドは、execに渡された引数の合計サイズと環境サイズの最大値を返します。