197

次のような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

ただし、コマンドが終了するまで各行を処理してから次の行に移動するのは非常に時間がかかります。たとえば、一度に 20 行を処理し、終了したら別の 20 行を処理したいと考えています。

コマンドをバックグラウンドに送信して続行することを考え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固有のソリューションは何の役にも立ちません。

4

4 に答える 4

332

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 です。

于 2013-10-23T13:35:42.290 に答える
7

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

wait

すべてのバックグラウンド ジョブが終了すると、スクリプトは待機して続行します。

于 2013-10-23T13:41:18.573 に答える