これがバックグラウンドで複数のシーケンシャルプロセスを開始する正しい方法ですか?
for i in {1..10}; do
for j in {1..10}; do
run_command $i $j;
done &
done;
場合によっては、すべてをj
順次処理する必要がありますi
が、すべてをi
同時に処理する必要があります。
答え1
あなたが持っている外部ループは基本的に
for i in {1..10}; do
some_compound_command &
done
some_compound_command
これにより、バックグラウンドで10個の同時インスタンスが起動されます。できるだけ早く開始されますが、正確には「同時」(some_compound_command
必要な場合など)ではありません。非常に時間が短い場合は、最後のジョブが開始される前に最初のジョブが完了する可能性が高くなります。
それがループであるという事実はsome_compound_command
重要ではありません。つまり、表示されるコードは次のようになります。正しい内部j
ループの繰り返しは順次実行されますが、内部ループのすべてのインスタンス(i
外部ループの各繰り返しごとに1つ)が同時に開始されます。
覚えておくべき唯一のことは、各バックグラウンドジョブがサブシェルで実行されることです。これは、内部ループの1つのインスタンス内で行われた環境の変更(たとえば、現在の作業ディレクトリへの変更を使用してシェル変数の値を変更するcd
など)が特定のバックグラウンドタスクの外部に表示されないことを意味します。
wait
少なくともスクリプトが終了する前に、すべてのバックグラウンドジョブが実際に完了するのを待つために、ループの後にステートメントを追加できます。
for i in {1..10}; do
for j in {1..10}; do
run_command "$i" "$j"
done &
done
wait
答え2
GNU Parallelがある場合は、次のことができます。
parallel -j0 'for j in {1..10}; do run_command {} $j; done' ::: {1..10}
1つの利点は、並列実行の出力がrun_commands
混在しないことです。