1. ホーム
  2. linux

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

2022-04-20 05:56:33

質問

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

しかし、1行1行をコマンドが終了するまで処理し、次のコマンドに移るのは非常に時間がかかります。例えば、20行を一度に処理し、それが終了したらまた20行を処理したいのですが、どうすればよいでしょうか?

そこで考えたのが wget LINK1 >/dev/null 2>&1 & しかし、4000行もあるため、パフォーマンスの問題はもちろん、同時に起動するプロセスの数にも制限があるため、良いアイデアとは言えません。

今考えている解決策のひとつは、あるコマンドがまだ実行されているかどうかをチェックすることで、たとえば20行後にこのループを追加することができます。

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

もちろん、この場合は行末に&を追加する必要があります。でも、このやり方は正しくないような気がします。

このスクリプトは動的に生成されるので、生成中に好きな計算をすることができますが、wgetを使う必要はありません。

どのように解決するのですか?

を使用します。 wait を内蔵しています。

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

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

からは GNUマニュアル :

wait [jobspec or pid ...]

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