web-dev-qa-db-ja.com

「引数リストが長すぎます」というエラーを引き起こす方法は?

質問のコンテキスト: POSIX仕様 によると、ARG_MAXはexec()へのコマンドライン引数の最大lengthです関数のファミリー。これは私がそれが実際のnumber引数であると信じるように導いたが、明らかにそれはうまくいかなかった:

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

明らかに、これは8192項目を超える長さですが、正常に機能します。 D.W。の回答 によると、8192はおそらくKB単位のサイズです。ですから、以前の仮定は間違いでした。

これが実際の質問の出番です。実際にになるアイテムの量を8192 kB制限を超えて把握するにはどうすればよいですか?言い換えると、*.jpgタイプのグロブがArgument list too longエラーになるようにするには、どのような計算を実行する必要がありますか?

これは 単一のコマンド引数の最大サイズを定義するもの の複製ではないことに注意してください。 getconf ARG_MAXulimit -sの値について知っていますが、それは私の質問ではありません。限界を超えるサイズの引数を生成する方法を知る必要があります。つまり、エラーを回避する方法ではなく、エラーを取得する方法を見つける必要があります。

13

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

このループはi=8で終了します。

したがって、すぐに説明できない4バイトがあります(8つのうち4つは、PATH環境変数のnameに対応する必要があります)。これらは、4つの文字列PATHPATHの値、/bin/echo、およびx文字の長い文字列のnullターミネータです。

each引数は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
9
Kusalananda

多くの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コマンドの引数リストが長すぎるエラー 」を参照してください。

追伸問題の長さは、引数と環境を格納するために必要な実際のメモリ量です。引数のnumberとは関係ありません。

8
AlexP

システム上のすべてのファイルを一覧表示する代わりに、時間がかかり、疎なシステムでは機能しないため、コマンド

/bin/echo {1..200000}

エラーを生成するはるかに速い(163ms)方法です。私にとってARG_MAX2097152(2,097,152、200万のオーダー)ですが、コマンドは引き続きエラーになります。

シェルに{start..end}がない場合は、やや遅い(ただしファイルのリストよりも速い)を使用できます。

/bin/echo $(seq 1 200000)

いずれかのコマンドが機能しない場合は、機能するまで、bashがメモリ不足になるまで、またはseqがそれ以上カウントできないまで、終了値を増やしてください。

6
cat

新しいシェル(exit完了時に)を簡単に開始し、制限を低い値(100kバイト)に設定するには、次のようにします。

$ bash
$ ulimit -s 100

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

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

しかし、echoのようなものを使用することをお勧めします。ビルトインがエラーを引き起こさないかもしれないことを理解してください、このコマンドは正しく動作するはずです:

$ echo {000001..100000}6789

また、バイト数が上記の制限(1.1Mバイト)をはるかに超えていることにも注意してください。

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

しかし、このコマンドは機能しません:

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

制限は、シェルの環境サイズに追加される引数リストのサイズ(バイト単位)によって設定されます。

6
Isaac