Bash 也能实现并发命令队列?
Concurrent Shell Command Queues

最近我想加速 Bash 处理任务,同时限制并发数量,于是探索如何在 Bash 中构建线程池。虽然 Bash 的并发控制并不理想,但出于对 Shell 的热爱,我实现了一套基于 xargs 和 FIFO 的命令队列机制。这套方案支持动态提交命令、自动管理并发数,并兼容 Bash 和 Zsh。尽管存在输出不流式、无法检测失败等局限,但它为脚本自动化提供了新的思路。如果你熟悉 Bash 并想挑战极限,不妨试试这个方案;否则,Python 或 GNU parallel 可能是更稳妥的选择。
有人可能会问:为什么要在 Bash 里做这件事?毕竟它的并发控制并不好。
HN 评论区
16- js2
> 如何在限制并发数的同时并行运行 shell 命令。
根据具体任务,生成一个 Makefile 并运行:
make -j <concurrency>
> 我最初的用例涉及发起大量网络请求
这确实是我大约 20 年前开始考虑用 Makefile 处理并发问题的原因。为每个 URL 下载到一个文件定义一条规则。然后简单地运行 `make -j <jobs>`,使用我想要的并发数,额外的好处是:自动跳过已下载的文件。例如:
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,但没有那些烦人的引用声明。