Bashスクリプトで一度に100のプロセスを開始する

Bashスクリプトで一度に100のプロセスを開始する

Bashスクリプトには次のプログラムがあります

for i in {1..1000}
do
   foo i
done

パラメータを使用して関数をfoo1000回呼び出します。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次のようにすることもできます(zshksh93またはからbash):

xargs -I{} -P100 -a <(echo {1..1000}) foo {}

fooしかしそれは独立した命令でなければならない。シェル関数や組み込み関数では使用できません。

zsh'はzargs順番に実行されます。 100ジョブを開始し、すべてのジョブが返されるのを待ってから、100ジョブの次の配置を開始します。一方、GNUはxargs最大100個のジョブを実行し続けようとします。 100 件のジョブを開始し、別のジョブを開始して一度に 1 つずつ完了します。

この動作を実現するには、zshからバックグラウンドプロセスが返されるたびにトリガーされるxargsSIGCHLDでジョブプールを起動して管理できます。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

おすすめ記事