「パラメータリストが長すぎます」エラーが発生する方法は? [コピー]

「パラメータリストが長すぎます」エラーが発生する方法は? [コピー]

問題の背景:によるとPOSIX仕様、ARG_MAXは最大値です。長さ関数系列のコマンドライン引数ですexec()。これは本当だと信じています。数字しかし、これは明らかに動作しません。

$ ulimit -s
8192
$ touch {1..18000}.jpg
$ rm *.jpg
$ 

明らかに8192以上のアイテムがあるにもかかわらずうまくいきます。 ~によるとDWの回答8192サイズはkB単位と呼ばれます。明らかに、前の仮定は間違っていました。

実際の質問は次のとおりです。実際のアイテム数はどのようにわかりますか?〜する8192kBの制限を超えていますか?つまり、この*.jpgタイプのglobがArgument list too longエラーを引き起こすためにどのような計算を行う必要がありますか?

重複ではないので参考にしてください単一コマンド引数の最大サイズを定義する。私はそれを理解getconf ARG_MAXしてulimit -s大切にします。それは私の問題ではありません。私は方法を知る必要がありますサイズが制限を超える十分なパラメータを生成します。。つまり、エラーを回避するのではなく、エラーを取得する方法を見つける必要があります。

答え1

getconf ARG_MAX長いリスト生成を使用しx、それを引数として外部ユーティリティを呼び出すと、「パラメータリストが多すぎる」というエラーが生成されます。

$ /bin/echo $( perl -e 'print "x" x $ARGV[0]' "$(getconf ARG_MAX)" )
/bin/sh: /bin/echo: Argument list too long

エラーが発生する原因には環境と文字列の長さが/bin/echo含まれているため、以下を引くことで可能な最大数を見つけることができます。

$ env
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin

(このシェルをで始めたので、env -i sh環境には変数のみがあります)PATH

$ /bin/echo $( perl -e 'print "x" x ($ARGV[0] - length($ENV{"PATH"}) - length("/bin/echo"))' "$(getconf ARG_MAX)" )
sh: /bin/echo: Argument list too long

まだ長すぎます。どのくらい?

i=0
while ! /bin/echo $( perl -e 'print "x" x ($ARGV[0] - length($ENV{"PATH"}) - length("/bin/echo") - $ARGV[1])' "$(getconf ARG_MAX)" "$i" )
do
    i=$(( i + 1 ))
done

ループはforを終了しますi=8

だからすぐに解釈できない4バイトがあります(8バイトのうち4バイトは名前環境PATH変数)。これは、4つの文字列、PATH値、および長い文字列のnull終端文字です。PATH/bin/echox

気づくパラメーターはnullで終わるため、コマンドにパラメーターが多いほど、結合された長さは短くなります。


また、一般環境の効果を示すために、

$ export BIG=$( perl -e 'print "x" x $ARGV[0]' "$( getconf ARG_MAX )" )

$ /bin/echo hello
sh: /bin/echo: Argument list too long

$ /bin/echo
sh: /bin/echo: Argument list too long

答え2

多くのLinuxディストリビューションでは、次のコマンドを実行してARG_MAXの現在の値を確認できます。

getconf ARG_MAX

「パラメータリストが長すぎます」というメッセージを生成する簡単な方法は、たとえば、私のシステムで実際に長いパラメータリストを提供することです。

/bin/echo "$(find / -xdev 2> /dev/null)"

有効ですが

/bin/echo "$(find / -xdev 2> /dev/null)" "$(find / -xdev 2> /dev/null)"

生産する

bash: /bin/echo: Argument list too long

詳細な議論は「rm、cp、mvコマンドパラメータのリストが長すぎます。エラースタックオーバーフローにあります。

PS問題の長さは、パラメータと環境を保存するために必要な物理メモリの量です。それは何の関係もありません数字議論。

答え3

新しいシェルを起動しやすく(exit完了した後)、制限を低い値(100 KB)に設定するには、次の手順を実行します。

$ bash
$ ulimit -s 100

使用した例ではエラーが発生する可能性があります。

$ touch {1..100000}.jpg
bash: /usr/bin/touch: Argument list too long

しかし、このようなものを使用する方が良いですecho。組み込みコマンドがエラーを引き起こさない可能性があることを理解すると、次のコマンドが正しく機能します。

$ echo {000001..100000}6789

また、バイト数が上記の制限(1.1Mbyte)をはるかに超えています。

$ echo {000001..100000}6789 | wc -c
1100000

ただし、このコマンドは機能しません。

$ /bin/echo {000001..100000}6789
bash: /bin/echo: Argument list too long

制限は、シェル環境サイズに追加されたパラメータリストのサイズ(バイト単位)に設定されます。

答え4

このコマンドはシステム上のすべてのファイルをリストしないため、時間がかかり、スパースシステムでは機能しません。

/bin/echo {1..200000}

エラーを生成するより速い(163ms)方法です。私の場合は(2,097,152、約200万)、ARG_MAXコマンド2097152はまだ間違っています。

シェルが存在しない場合は、{start..end}少し遅いものを使用できます(ただし、ファイルの一覧よりも高速です)。

/bin/echo $(seq 1 200000)

両方のコマンドのいずれかが機能しない場合は、動作するまで、bashメモリが不足するまで、またはseq計算できないまで最終値を増やします。

関連情報