29

に渡すことができるコマンドラインの長さはどれくらいsh -c ''ですか? (bash および bourne シェル)

この制限は、OS からの制限よりもはるかに低くなっています (最新の Linux の場合)。

例えば:

$ /bin/true $(seq 1 100000)
$ /bin/sh -c "/bin/true $(seq 1 100000)"
bash: /bin/sh: Argument list too long

そして、どうすればこの問題を回避できますか?

アップデート

ここでは役に立たないことに注意してgetconfください (これはシステムの制限ではないため)。

$ seq 1 100000 | wc -c
588895
$ getconf ARG_MAX
2097152

アップデート #2

ここでポイントが何であるかを理解しました。これはシェルの制限ではなく、システムの制限ですが、引数リスト全体ではなく、各引数の長さに対するものです。

$ /bin/true $(seq 1 100000)
$ /bin/true "$(seq 1 100000)"
bash: /bin/true: Argument list too long

CodeGnome さん、説明ありがとうございます。

4

4 に答える 4

27

TL;DR

1 つの引数は MAX_ARG_STRLEN より短くする必要があります。

分析

このリンクによると:

また、2.6.23 以降の追加の制限として、1 つの引数を MAX_ARG_STRLEN より長くしてはなりません (131072)。これは、「sh -c 'Generated with long arguments'」のような長い呼び出しを生成する場合に関連する可能性があります。

これはまさにOPによって特定された「問題」です。許可される引数の数は非常に多い場合がありますが (「 」を参照getconf ARG_MAX)、引用符で囲まれたコマンドを/bin/shに渡すと、シェルは引用符で囲まれたコマンドを単一の文字列として解釈します。OP の例では、拡張された引数リストの長さではなく、MAX_ARG_STRLEN 制限を超えるのはこの単一の文字列です。

実装固有

引数の制限は実装固有です。ただし、この Linux Journal の記事では、システム制限を引き上げるなど、それらを回避する方法がいくつか提案されています。これは OP には直接適用できないかもしれませんが、それでも一般的なケースでは役に立ちます。

他のことをする

OPの問題は、実際には実際の問題ではありません。問題は、現実の問題を解決しない恣意的な制約を課すことです。

ループを使用すると、これを簡単に回避できます。たとえば、Bash 4 の場合:

for i in {1..100000}; do /bin/sh -c "/bin/true $i"; done

うまく動作します。ループを通過するたびにプロセスを生成しているため、確かに遅くなりますが、経験しているコマンドラインの制限を確実に回避できます。

あなたの本当の問題を説明してください

ループで問題が解決しない場合は、質問を更新して、非常に長い引数リストを使用して実際に解決しようとしている問題を説明してください。任意の行の長さの制限を調査することは学術的な演習であり、スタック オーバーフローのトピックではありません。

于 2012-07-13T17:52:26.607 に答える
4

そのエラーメッセージは表示されません。私の秘密?一重引用符:

/bin/sh -c '/bin/true $(seq 1 100000)'

二重引用符を使用すると、すべてのシェルでそのエラーが発生します。

$ /bin/sh -c "/bin/true $(seq 1 100000)"
-bash: /bin/sh: Argument list too long
$ /bin/bash -c "/bin/true $(seq 1 100000)"
-bash: /bin/bash: Argument list too long
$ /bin/ksh -c "/bin/true $(seq 1 100000)"
-bash: /bin/ksh: Argument list too long
$ /bin/zsh -c "/bin/true $(seq 1 100000)"
-bash: /bin/zsh: Argument list too long

コマンドの実行に使用されているシェルに関係なく、Bash がエラー「-bash: ...」を発行しているという事実によって証明されるように、二重引用符が使用されている場合、引数リストは現在のシェルで展開されます。ちなみに、私のシステムshにはDashがあります。

これは、他の「ホスト」シェルにも当てはまります。

$ dash
$ /bin/bash -c '/bin/true $(seq 1 100000)'
$ /bin/bash -c "/bin/true $(seq 1 100000)"
dash: /bin/bash: Argument list too long

患者: 先生、これをすると痛いです」
医者: やめてください。

于 2012-07-13T18:48:55.577 に答える
0

私のOSでは、二分法によって得られた最大長です

/bin/sh -c "/bin/true $(perl -e 'print"a"x131061')"

したがって、131071が得られます

しかし、これほど長い行を持つ理由はありません。多数の引数が原因である場合は、代わりに "$@" を使用できます。例えば

/bin/sh -c 'command "$@"' -- arg1 arg2 .. argn
于 2012-07-13T18:27:44.540 に答える
0

最初の行としてファイルを作成し#!/bin/shてから、残りのコマンドを後続の行に配置しますか? :)

さらに深刻なことに、オプションを使用して STDIN からコマンドを読み取ることも-sできるため、長いコマンド ラインを生成して、/bin/sh -s

于 2012-07-13T17:46:18.817 に答える