bashがforループと衝突する

bashがforループと衝突する

この質問はマイナーかもしれませんが、この単純なforループを使用すると

for i in {1..10000000}; do echo "$i" line >> file
done

しばらく詳しく説明した後、私のシェルがクラッシュし(ターミナルエミュレータのタブが自動的に閉じて)file生成されませんでした。

これはGNU bash, version 4.1.11(2)-release

メモリ制限のためですか、それとも別の問題のためですか?それでは、この制限はどのくらいでなければなりませんか?

それはそれでうまくいく{1..1000000}でしょう。

答え1

これが発生するのは、コマンドが呼び出される前に角かっこが拡張されるためです。したがって、実際には次のようなコマンドが生成されます。

for i in 1 2 3 ... 10000000 ; do ... 

..それでメモリを大量に消費するか、競合が発生します

長いループで作業するときの解決策は、bashのCスタイル構文を使用することです:

for ((i = 1; i <= 10000000; i++))
do 
    ...
done

または、他のシェルとの互換性を維持するには、whileループにパイプすることもできます。

seq 1 10000000 | while IFS= read -r line
do
     ...
done

答え2

はい、私のbashプロセスには、このコマンドを実行するために多くのメモリが必要です。私の場合は1.9GB(x86_64)でした。制限に達した可能性があり、カーネルメモリ不足キラーがそれを削除しました。私には本当に効果があります。約3分かかります。

 $ wc -l file
 10000000 file
 $ tail -n1 file
 10000000 line
 $ ls -hl file
 -rw-r--r-- 1 seb users 123M Sep  5 13:19 file

RAMの制限仮定の確認:スワップスペースがあると、いっぱいになるのを見ることができます。htopこの目的のために、例えば。

ループを100,000,000個以上の要素に増やすと、プロセスも10倍のRAMを消費します18GB

@user000001 さんが説明と代替案を提示しました。私はテストしましたCスタイルの構文(彼は):

for ((i = 1; i <= 10000000; i++))
do 
 ...
done

このプロセスは、通常のbashプロセスよりも多くのRAMを使用しません。

関連情報