我需要限制并行执行的进程数。例如我想执行这个伪命令行:
export POOL_PARALLELISM=4
for i in `seq 100` ; do
pool foo -bar &
done
pool foo -bar # would not complete until the first 100 finished.
因此,尽管有 101 个 foo
正在排队等待运行,但在任何给定时间只有 4 个会运行。 pool
将 fork()/exit() 并将剩余的进程排队直到完成。
有没有一种简单的机制可以用 Unix 工具来做到这一点? at
和 batch
不适用,因为它们通常在一分钟内调用并按顺序执行作业。使用队列不一定是最好的,因为我希望这些同步。
在我编写一个使用信号量和共享内存的 C 包装程序然后调试我肯定会介绍的死锁之前,任何人都可以推荐一个 bash/shell 或其他工具机制来完成这个。
最佳答案
这个工具肯定没必要自己写,有几个不错的选择。
制作
make
可以很容易地做到这一点,但它确实广泛依赖于文件 来驱动该过程。 (如果您想对生成输出文件的每个输入文件运行一些操作,这可能很棒。)-j
命令行选项将运行指定数量的任务,- l
load-average 命令行选项将指定在开始新任务之前必须满足的系统平均负载。 (如果您想“在后台”做一些工作,这可能会很好。不要忘记 nice(1)
命令,它在这里也有帮助。)
因此,一个用于图像转换的快速(且未经测试)Makefile
:
ALL=$(patsubst cimg%.jpg,thumb_cimg%.jpg,$(wildcard *.jpg))
.PHONY: all
all: $(ALL)
convert $< -resize 100x100 $@
如果您使用 make
运行它,它将一次运行一个。如果您使用 make -j8
运行,它将运行八个独立的作业。如果你运行 make -j
,它会启动数百个。 (在编译源代码时,我发现两倍的核心数是一个很好的起点。这让每个处理器在等待磁盘 IO 请求时有事可做。不同的机器和不同的负载可能会有所不同。)
xargs
xargs
提供了--max-procs
命令行选项。如果可以使用 ascii NUL
分隔的输入命令或换行分隔的输入命令,基于单个输入流将并行进程分开,这是最好的。 (好吧,-d
选项让您可以选择其他选项,但这两个选项很常见且简单。)这让您受益于使用 find(1)
的强大功能文件选择语法,而不是像上面的 Makefile
示例那样编写有趣的表达式,或者让您的输入与文件 完全无关。 (考虑一下,如果您有一个程序可以将大的合数分解为质因数——让该任务适合 make
充其量也很尴尬。xargs
可以轻松完成。)
前面的例子可能看起来像这样:
find . -name '*jpg' -print0 | xargs -0 --max-procs 16 -I {} convert {} --resize 100x100 thumb_{}
并行
moreutils
包(至少在 Ubuntu 上可用)提供了 parallel
命令。它可以以两种不同的方式运行:对不同的参数运行指定的命令,或者并行运行不同的命令。前面的示例可能如下所示:
parallel -i -j 16 convert {} -resize 100x100 thumb_{} -- *.jpg
beanstalkd
beanstalkd
程序采用完全不同的方法:它提供一个消息总线供您提交请求,作业服务器阻止正在输入的作业,执行作业,然后返回等待队列中的新作业。如果您想将数据写回启 Action 业的特定 HTTP 请求,这可能不是很方便,因为您必须自己提供该机制(可能是 beanstalkd
服务器上的不同“管” ),但如果最终结果是将数据提交到数据库、电子邮件或类似的异步方式,这可能是最容易集成到现有应用程序中的方法。
关于bash - 同步 Unix 池化进程的简单机制是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9473768/