我希望能够运行一系列命令,而无需事先知道具体有多少和哪些。这些命令通常是一些计算,每个计算需要几个小时/几天。我需要一些方法来修改后验命令列表,因为它在集群上运行,我需要提前保留节点。
我希望它(无论它是什么)(i)在它运行时读取命令并在处理器释放时继续启动它们,以及(ii)在没有更多命令运行时退出。
实现这一目标的最简单方法是什么?
编辑:这有效(与 GNU 并行)
首先,按照答案中的建议,修改parallel
(例如/usr/bin/parallel
),改变
# Ignore the rest of input file
while (<$fh>) {}
至
# Ignore the rest of input file
close $fh;
然后像这样测试:
seq 10 > test; tail -f test | parallel -uE EXIT 'echo {}'
笔记
- “-u”用于“ungroup”,以便所有行都在它们到来时被读取、执行和打印,并且 procs 可用
- “-E EXIT”是我们可以杀死的:在写完 EXIT 之后,必须写另一个(任意)字符串,这样 'tail -f' 才会死掉。(如果没有上述并行修改将保持流打开,这将不起作用)
- 如果流为空且 CPU 空闲,它不会退出:我认为这是一个更复杂的问题,也涉及同步,尽管它可以通过类似
if(items_processed>0 && nprocs_running==0) exit
. 然后仍然存在杀死尾巴的问题,但这可能会通过定期向输入文件写入一些虚假内容来以一种丑陋的方式解决。
我试过的
我能想到的最简单的语法是这样的,使用 GNU 并行:
parallel < command-list.txt
[...some time later...]
echo "this-command-I-forgot" >> command-list.txt
这很好用......除了,如果命令的数量小于 CPU 的数量(这很常见,我可能从 16-cpu 机器上的 10 个进程开始)它将遇到 EOF,关闭流,我看到无法添加更多命令。因此,只要这些正在运行的命令结束,它就会完成。
为了避免 EOF 问题,我想我可以用 tail 跟随流
tail -n+0 -f command-list.txt | parallel --eof=EXIT
例如在这个简单的测试中:
seq 10 > command-list.txt
tail -n+0 -f command-list.txt | parallel -j2 --eof=EXIT 'sleep 1 && echo {}'
echo "this-command-I-forgot" >> command-list.txt
这非常接近,我可以添加命令并且它不会关闭文件。但是,它永远不会结束,并且在读取“退出”时不会停止,而是挂起。我不确定为什么。也许它正在读取块。(??)此外,如果所有进程都已完成并且文件中没有任何事情可做,它不会停止。
(编辑这可能与答案中提出的错误有关)
或者,我可以想象一些事情,为每个 CPU 启动一些带有“等待 PID”的子进程,但它看起来过于复杂,而且这似乎正是 GNU/parallel 应该做的事情。
感谢您的任何帮助或建议!
根据此处 的评论进行编辑,这至少会退出,但它首先需要关键字“退出”。
sh -c 'tail -n+0 -f command-list.txt | { sed "/EXIT/Q" && kill -9 $$ ;}' | parallel -j2 'sleep 1 && echo {}'
正如该线程中所建议的,也可以使用“xargs -P2”而不是“parallel -j2”,但这并不能解决问题。