Bashだけで並列実行を制限するコマンドキューを作る
Concurrent Shell Command Queues

Bashで並列処理を高速化しつつ同時実行数を制限したい——そのためにFIFOとxargs -Pを組み合わせ、コマンドを後から投入できるキューを自作した。queue_start、queue_submit、queue_waitの3関数で構成され、BashとZshの両方で動作する。ただし出力のストリーミング不可や終了処理の乱暴さなど既知の制約も多く、筆者自身もPythonなど別言語の利用を勧めている。
Bashが好きで、挑戦してみたかったからです。それでも、Pythonなど別の言語を使ったほうがよいでしょう。
HNでの議論
16- js2
> シェルコマンドを並列実行しつつ、同時実行数を制限する方法。
タスクによっては、Makefileを生成して次のように実行します:
make -j <同時実行数>
> 私の元々のユースケースは、大量のWebリクエストを行うことでした
これはまさに、おそらく20年前に私が並列実行のためにMakefileを使うことを考えたきっかけとなったユースケースです。各URLをファイルにダウンロードするルールを作ります。そして、好きな同時実行数でシンプルに `make -j <ジョブ数>` を実行するだけです。おまけに、既にダウンロード済みのファイルは自動的にスキップされます。例えば:
BASE := https://example.com/files
FILES := a.txt b.txt c.txt d.txt e.txt
.DELETE_ON_ERROR:
all: $(FILES)
$(FILES):
curl -sS --fail --max-time 30 -o $@ $(BASE)/$@
あるいは、ブログ記事の例の一つを模倣するなら:
SHELL := bash
.SHELLFLAGS := -o pipefail -c
N := 1 2 3 4 5
REQS := $(N:%=req-%)
.PHONY: all $(REQS)
all: $(REQS)
$(REQS): req-%:
@curl -sS --fail-with-body --max-time 10 -X POST -H 'Content-Type: application/json' \
-d '{"request": $*}' https://postman-echo.com/post | jq -c .json
実行方法:
$ make -O -j 3
> 実行したいコマンドをすべて事前に知っている必要はなく、時間をかけてコマンドを投入できます。
ああ、そうですね。それはMakeを `xargs -P` / GNU `parallel` と同じカテゴリに入れることになり、もっと巧妙なものが必要になります。
- reconquestio
GNU Parallelのsemもあります:https://www.gnu.org/software/parallel/sem.html
sem --id jobs -j 2 'sleep 1; echo FIRST'
sem --id jobs -j 2 'echo SECOND'
sem --id jobs -j 2 'echo THIRD'
sem --id jobs --wait
SECOND
THIRD
FIRST
- 0cf8612b2e1e
これにはpueueが本当に気に入っています。軽量なslurmやparallelのようなもので、引用通知に悩まされることもありません。