web-dev-qa-db-ja.com

Bash:バックグラウンドでの複数のforループ

これは、複数の順次処理をバックグラウンドで開始する正しい方法ですか?

for i in {1..10}; do
    for j in {1..10}; do
        run_command $i $j;
    done &
done;

すべてのjは指定されたiに対して順番に処理する必要がありますが、すべてのiは同時に処理する必要があります。

8

あなたが持っている外側のループは基本的に

for i in {1..10}; do
    some_compound_command &
done

これにより、some_compound_commandの10個の同時インスタンスがバックグラウンドで開始されます。それらは可能な限り速く開始されますが、「すべて同時に」ではありません(つまり、some_compound_commandvery少し時間がかかる場合、最初のものは最後のものが始まる前に終了する可能性があります) )。

some_compound_commandがループであることは重要ではありません。つまり、表示するコードは正しいであり、内側のj- loopの反復は順次実行されますが、内側のループのすべてのインスタンス(外側の反復ごとに1つ) i- loop)は同時に開始されます。

覚えておくべき唯一のことは、各バックグラウンドジョブがサブシェルで実行されることです。つまり、内部ループの1つのインスタンスで環境に加えられた変更(たとえば、シェル変数の値の変更、現在の作業ディレクトリのcdによる変更など)は、その特定のバックグラウンドジョブの外には表示されません。 。

追加したいのは、ループの後のwaitステートメントで、少なくともスクリプトが終了する前に、すべてのバックグラウンドジョブが実際に終了するのを待つだけです。

for i in {1..10}; do
    for j in {1..10}; do
        run_command "$i" "$j"
    done &
done

wait
8
Kusalananda

あなたがGNU Parallelを持っているなら、あなたはそうするでしょう:

parallel -j0 'for j in {1..10}; do run_command {} $j; done' ::: {1..10}

利点の1つは、並列実行からの出力run_commandsは混合しません。

3
Ole Tange