web-dev-qa-db-ja.com

シェル可変容量

次のようなステートメントがあるシェルスクリプトがあるとします。

a=$(find / -type f)

これは、変数「a」に格納されるファイルパスを持つファイルの特定のリストがあることを示しています。

保存できる最大制限または行数はいくつですか。どうすれば見つけられますか?

18
Vijay

IIRC、bashは、変数が格納できるデータの量に制限を課しません。ただし、bashが実行された環境によって制限されます。より包括的な説明については、 この回答 を参照してください。

9
Shawn Chin

データポイントとして、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であるため、ここでは明らかにいくつかの数容量の制限に達しています。)

2
Daniel Griscom

Daniel Griscomのスクリプトのわずかな改善:

  1. スクリプトが使用しているメモリの量を示すものを追加できます(ループ内の最後のコマンドの追加を参照)
  2. さまざまなシェル環境を試すことができます(私のテストでは、bashがzshと同じサイズの変数に対して約5倍のメモリを使用することが示されました-以下のテストを自分で行うことができます)

注: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
1
cepal67

私が知っているように、限界を見つける唯一の方法は経験的な方法によるものです。次のシェルスクリプトを実行して、完了するまで待ちます。

limit=1
while true
do
  limit=`echo 1+$limit|bc`
  a=' '$a
  echo $limit
done
1
FerranB

Bashの変数サイズに制限はないと思いますが、本当にシェルに6GBの変数が必要ですか(もちろんulimit -aが必要です)?

コマンドラインには確かに制限があります。 grep <pattern> $TEN_MILLION_FILENAMESは機能しません。実際、$TEN_MILLION_FILESを使用してコマンドを生成することは非常に困難です。ディレクトリごと、または一時ファイルなど、他の戦略が必要です。

1
bobbogo

私が見る限り、標準は制限を課していません。しかし、基礎となるシステムはそうかもしれません。一部のAIXで制限にぶつかったことがあることを思い出します。

Configureが引数の最大数をチェックするようにチェックすることができます-エラーが見つかるまで試してください。式var(i)=concatenation(var(i-1),var(i-1))を使用したある種の反復アプローチ。遅かれ早かれ、制限に達します(少なくとも処理中のメモリ制限)。

0
user332325