次のようなステートメントがあるシェルスクリプトがあるとします。
a=$(find / -type f)
これは、変数「a」に格納されるファイルパスを持つファイルの特定のリストがあることを示しています。
保存できる最大制限または行数はいくつですか。どうすれば見つけられますか?
IIRC、bashは、変数が格納できるデータの量に制限を課しません。ただし、bashが実行された環境によって制限されます。より包括的な説明については、 この回答 を参照してください。
データポイントとして、2.8 GHz Intel Corei7を搭載したMacbookPro Retinaに組み込まれているbashを使用して、OS X10.10.5で次のスクリプトを試しました。
#!/bin/bash
humombo="X"
while true; do
humombo="$humombo$humombo"
echo "Time $(date "+%H:%M:%S"), chars $(echo "$humombo" | wc -c)"
done
結果:サイズは何度も何度も喜んで2倍になりました(サイズには1行の終わりに余分なバイトが含まれていることに注意してください)。 humombo
が4MBを超えると、状況は遅くなり始めました。 256MBから512MBへの倍増には48秒かかり、その後スクリプトが爆発しました。
mbpe:~ griscom$ ./delme.sh
Time 16:00:04, chars 3
Time 16:00:04, chars 5
Time 16:00:04, chars 9
Time 16:00:04, chars 17
Time 16:00:04, chars 33
Time 16:00:04, chars 65
Time 16:00:04, chars 129
Time 16:00:04, chars 257
Time 16:00:04, chars 513
Time 16:00:04, chars 1025
Time 16:00:04, chars 2049
Time 16:00:04, chars 4097
Time 16:00:04, chars 8193
Time 16:00:04, chars 16385
Time 16:00:04, chars 32769
Time 16:00:04, chars 65537
Time 16:00:04, chars 131073
Time 16:00:04, chars 262145
Time 16:00:04, chars 524289
Time 16:00:04, chars 1048577
Time 16:00:04, chars 2097153
Time 16:00:05, chars 4194305
Time 16:00:05, chars 8388609
Time 16:00:07, chars 16777217
Time 16:00:09, chars 33554433
Time 16:00:15, chars 67108865
Time 16:00:27, chars 134217729
Time 16:00:51, chars 268435457
Time 16:01:39, chars 536870913
bash(80722,0x7fff77bff300) malloc: *** mach_vm_map(size=18446744071562072064) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
./delme.sh: xrealloc: cannot allocate 18446744071562068096 bytes
mbpe:~ griscom$
2つのメモ:
クラッシュは、単一の変数の容量の制限に達するのではなく、プロセス全体がメモリを大量に消費したことによるものだと思います。
これで遊んでいる間、私は同じコマンドをインタラクティブに実行し、ループが終了するとbashが壊れました。私は何かをするために新しいターミナルウィンドウを開かなければなりませんでした。したがって、メモリ割り当てが多すぎると、未知の方法でbashが壊れます。私の推測では、スクリプト内でそれを行うと、終了時にクリーンアップされます。
編集:強力なUbuntu18システムで同じコードを試しました:
Time 18:03:02, chars 3
Time 18:03:02, chars 5
Time 18:03:02, chars 9
Time 18:03:02, chars 17
Time 18:03:02, chars 33
Time 18:03:02, chars 65
Time 18:03:02, chars 129
Time 18:03:02, chars 257
Time 18:03:02, chars 513
Time 18:03:02, chars 1025
Time 18:03:02, chars 2049
Time 18:03:02, chars 4097
Time 18:03:02, chars 8193
Time 18:03:02, chars 16385
Time 18:03:02, chars 32769
Time 18:03:02, chars 65537
Time 18:03:02, chars 131073
Time 18:03:02, chars 262145
Time 18:03:02, chars 524289
Time 18:03:02, chars 1048577
Time 18:03:02, chars 2097153
Time 18:03:02, chars 4194305
Time 18:03:02, chars 8388609
Time 18:03:03, chars 16777217
Time 18:03:04, chars 33554433
Time 18:03:07, chars 67108865
Time 18:03:12, chars 134217729
Time 18:03:23, chars 268435457
Time 18:03:43, chars 536870913
./delme.sh: xrealloc: cannot allocate 18446744071562068096 bytes
半分以下の時間で、もう少しきれいに死にましたが、同じ文字サイズでした。 (BTW、エラーメッセージの数値(10進数18446744071562068096)は0xffff ffff 8000 0080であるため、ここでは明らかにいくつかの数容量の制限に達しています。)
Daniel Griscomのスクリプトのわずかな改善:
注:cygwinは/ procを完全に複製しないため、スクリプトをCygwin内で実行すると、「VmPeak」行の出力は空になります(基本的に「VmPeak」値がありませんが、おそらくそのような場合は「VmSize」を選択できます。場合?)
$ cat delme.sh
#!/bin/zsh
humombo="X"
pid=$$
while true; do
humombo="$humombo$humombo"
echo "Time $(date "+%H:%M:%S"), chars $(echo "$humombo" | wc -c)"
echo -n "Memory usage: "
grep ^VmPeak /proc/${pid}/status
done
私が知っているように、限界を見つける唯一の方法は経験的な方法によるものです。次のシェルスクリプトを実行して、完了するまで待ちます。
limit=1
while true
do
limit=`echo 1+$limit|bc`
a=' '$a
echo $limit
done
Bashの変数サイズに制限はないと思いますが、本当にシェルに6GBの変数が必要ですか(もちろんulimit -a
が必要です)?
コマンドラインには確かに制限があります。 grep <pattern> $TEN_MILLION_FILENAMES
は機能しません。実際、$TEN_MILLION_FILES
を使用してコマンドを生成することは非常に困難です。ディレクトリごと、または一時ファイルなど、他の戦略が必要です。
私が見る限り、標準は制限を課していません。しかし、基礎となるシステムはそうかもしれません。一部のAIXで制限にぶつかったことがあることを思い出します。
Configureが引数の最大数をチェックするようにチェックすることができます-エラーが見つかるまで試してください。式var(i)=concatenation(var(i-1),var(i-1))
を使用したある種の反復アプローチ。遅かれ早かれ、制限に達します(少なくとも処理中のメモリ制限)。