次のような 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 固有のソリューションは役に立ちません。
ベストアンサー1
wait
組み込みのものを使用します:
process1 &
process2 &
process3 &
process4 &
wait
process5 &
process6 &
process7 &
process8 &
wait
上記の例では、4 つのプロセスがprocess1
バックprocess4
グラウンドで開始され、シェルはそれらが完了するまで待機してから次のセットを開始します。
からGNUマニュアル:
wait [jobspec or pid ...]
各プロセス ID pid またはジョブ仕様 jobspec で指定された子プロセスが終了するまで待機し、待機した最後のコマンドの終了ステータスを返します。ジョブ仕様が指定されている場合は、ジョブ内のすべてのプロセスを待機します。引数が指定されていない場合は、現在アクティブなすべての子プロセスを待機し、戻りステータスは 0 になります。jobspec も pid もシェルのアクティブな子プロセスを指定していない場合、戻りステータスは 127 になります。