Bashスクリプトには次のプログラムがあります
for i in {1..1000}
do
foo i
done
パラメータを使用して関数をfoo
1000回呼び出します。i
複数のプロセスで実行されますが、同時に実行されないようにするにはどうすればよいですか?
だから私が持っているなら
for i in {1..1000}
do
foo i &
done
1000のプロセスがすべて同時に開始されますが、これは私が望むものではありません。
常に100個のプロセスを実行する方法はありますか?一部のプロセスが完了すると、1000回の繰り返しがすべて完了するまで、いくつかの新しいプロセスが開始されます。または、100個すべてが完了するのを待ってから100個を実行することもできます。
ベストアンサー1
zsh
代わりに使用してくださいbash
:
autoload -Uz zargs
zargs -P100 -I{} -- {1..1000} -- foo {}
しかし、GNUがある場合は、xargs
次のようにすることもできます(zsh
、ksh93
またはからbash
):
xargs -I{} -P100 -a <(echo {1..1000}) foo {}
foo
しかしそれは独立した命令でなければならない。シェル関数や組み込み関数では使用できません。
zsh
'はzargs
順番に実行されます。 100ジョブを開始し、すべてのジョブが返されるのを待ってから、100ジョブの次の配置を開始します。一方、GNUはxargs
最大100個のジョブを実行し続けようとします。 100 件のジョブを開始し、別のジョブを開始して一度に 1 つずつ完了します。
この動作を実現するには、zshからバックグラウンドプロセスが返されるたびにトリガーされるxargs
SIGCHLDでジョブプールを起動して管理できます。trap
(
todo=( {1..1000} ) max=100
TRAPCHLD() {
while (( $#jobstates < max && $#todo )); do
foo $todo[1] & shift 1 todo
done
}
: start &
while (( $#todo )) wait
)
ここでは、新しいタスクのリストを取得するためにサブシェルでそれを実行する必要があります。 TRAPCHLDトラップの実行中にSIGCHLDがブロックされるため、トラップはそれ自体を再入力しないでください。これにより、競合状態やリストへの同時アクセスを防止する必要性を回避する必要があります$todo
。