web-dev-qa-db-ja.com

Bash、バックグラウンドプロセスを実行させて他のプロセスを待つ方法は?

(まだ)別のwait&&&制御フローの質問。

次のようなスクリプトで、できるだけ多くの作業を同時に実行したいとします。

# may take some hours
something InputA > IrrelevantA &
something InputB > IrrelevantB &

# may take an hour
(
   somethingElse InputA > OutputA &
   somethingElse InputB > OutputB &
)&& combine OutputA OutputB > Result

...morestuff

質問1:スクリプトでは、combineは、両方のsomethingElseプロセスが続行する間、両方のsomethingプロセスが完了するのを待機しますか?

質問2:そうでない場合-そして、そうではないと思われる場合-上記のcombineプロセスが機能している間、somethingElseが両方のsomethingプロセスのみを待機するようにする方法バックグラウンドで離れていますか?

11

あなたの例では、combineコマンドはサブシェルが終了するとすぐに実行されます(最後のバックグラウンドプロセスがエラーなしで開始された場合)。 waitコマンドがないため、サブシェルはジョブの開始直後に終了します。

2つ以上の同時バックグラウンドプロセスの戻り値に基づいてコマンドを実行する場合、戻り値に一時ファイルを使用する以外に方法はありません。これは、waitが返すことができるのは、待機しているプロセスのoneの戻り値のみであるためです。また、バックグラウンドプロセスは、戻り値を取得するためにサブシェルで実行する必要があるため、変数に格納できません。あなたがすることができます:

something InputA >IrrelevantA &
something InputB >IrrelevantB &

tmp1=$(mktemp)
tmp2=$(mktemp)

( somethingElse InputA >OutputA; echo $? >"$tmp1" ) &
proc1=$!

( somethingElse InputB >OutputB; echo $? >"$tmp2" ) &
proc2=$!

wait "$proc1" "$proc2"

read ret1 <"$tmp1"
read ret2 <"$tmp2"
[ "$ret1" = 0 && "ret2" = 0 ] && combine OutputA OutputB >Result

rm "$tmp1" "$tmp2"

戻り値が本当に気にならない場合は、ジョブを通常どおり開始してwaitを使用できます。

something InputA >IrrelevantA &
something InputB >IrrelevantB &

somethingElse InputA >OutputA &
proc1=$!

somethingElse InputB >OutputB &
proc2=$!

wait "$proc1" "$proc2"
combine OutputA OutputB >Result
13
Graeme

ファイルOutputAOutputBを保存する必要がなく、Resultのみを気にする場合は特に、プロセス置換がより効率的でしょうか?ディスクへの書き込みでI/Oが遅い場合、ファイルOutputAOutputBの保存がレート制限ステップになる可能性があるため、これは特に時間の節約になりますか?

_combine  <(somethingElse InputA)  <(somethingElse InputB)  >  Result
_

プロセス置換を使用すると、出力をファイルに保存して「結合」ステップで入力として読み取る代わりに、コマンドを<(..here..)内に配置できます。

メモリが制限であり、outputAおよびoutputBのサイズがメモリが保持できるサイズよりも大きい場合、目的全体を無効にしますか?

combineは、両方のプロセスが完了するまで待機してから実行を開始しますか?

3
TW Tan

waitコマンドを使用できます。

(echo starting & sleep 10 & wait) && echo done

「開始」の行がすぐに発生し、「完了」が10秒間待機することがわかります。

2
psusi