web-dev-qa-db-ja.com

限られた数のコマンドを並列に処理するBashスクリプト

このようなbashスクリプトがあります。

#!/bin/bash
wget LINK1 >/dev/null 2>&1
wget LINK2 >/dev/null 2>&1
wget LINK3 >/dev/null 2>&1
wget LINK4 >/dev/null 2>&1
# ..
# ..
wget LINK4000 >/dev/null 2>&1

しかし、コマンドが完了するまで各行を処理してから次の行に移動するのは非常に時間がかかります。

私はwget LINK1 >/dev/null 2>&1 &がバックグラウンドにコマンドを送り続けようと考えました、しかしここに4000行があります、これは私がパフォーマンス問題を抱えることを意味します。良いアイデア。

今考えている解決策の1つは、コマンドの1つがまだ実行中かどうかを確認することです。たとえば、20行後にこのループを追加できます。

while [  $(ps -ef | grep KEYWORD | grep -v grep | wc -l) -gt 0 ]; do
sleep 1
done

もちろんこの場合、行末に&を追加する必要があります。しかし、これが正しい方法ではないと私は感じています。

それで、どのように私は実際にそれぞれの20行を一緒にグループ化し、次の20行に行く前にそれらが終わるのを待つか、このスクリプトは動的に生成されます。 wgetを使用してください、それは単なる例でしたので、wget特有のどんな解決策も私にはうまくいくつもりはありません。

175
AL-Kateb

wait組み込みを使用します。

process1 &
process2 &
process3 &
process4 &
wait
process5 &
process6 &
process7 &
process8 &
wait

上記の例では、4つのプロセスprocess1 ... process4がバックグラウンドで開始され、シェルはそれらが完了するまで待機してから次のセットを開始します。

GNUマニュアルから

wait [jobspec or pid ...]

各プロセスID pidまたはジョブ指定jobspecで指定された子プロセスが終了するのを待ち、最後に待機したコマンドの終了ステータスを返します。ジョブ仕様が指定されている場合は、そのジョブ内のすべてのプロセスが待機されます。引数が与えられていない場合、現在アクティブなすべての子プロセスが待機され、戻りステータスはゼロです。 jobspecもpidもシェルのアクティブな子プロセスを指定していない場合、戻り状況は127です。

308
devnull

parallel を参照してください。その構文はxargsに似ていますが、コマンドを並列に実行します。

84
choroba

実際、xargs並列にコマンドを実行できます。そのための特別な-P max_procsコマンドラインオプションがあります。 man xargsを参照してください。

57
Vader B

20個のプロセスを実行して次のコマンドを使用できます。

wait

あなたのスクリプトはすべてのバックグラウンドジョブが終了したときに待機し続けます。

7
Binpix