問題の背景:によると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/echo
x
気づく各パラメーターは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
計算できないまで最終値を増やします。