Bash 脚本并行处理有限数量的命令

Posted

技术标签:

【中文标题】Bash 脚本并行处理有限数量的命令【英文标题】:Bash script processing limited number of commands in parallel 【发布时间】:2013-11-01 19:33:37 【问题描述】:

我有一个如下所示的 bash 脚本:

#!/bin/bash
wget LINK1 >/dev/null 2>&1
wget LINK2 >/dev/null 2>&1
wget LINK3 >/dev/null 2>&1
wget LINK4 >/dev/null 2>&1
# ..
# ..
wget LINK4000 >/dev/null 2>&1

但是处理每一行直到命令完成然后移动到下一行非常耗时,例如我想一次处理 20 行,然后当它们完成时再处理 20 行。

我想过wget LINK1 >/dev/null 2>&1 &将命令发送到后台继续执行,但是这里有4000行这意味着我会遇到性能问题,更不用说我应该同时启动多少个进程所以这不是一个好主意。

我现在正在考虑的一个解决方案是检查其中一个命令是否仍在运行,例如在 20 行之后我可以添加这个循环:

while [  $(ps -ef | grep KEYWORD | grep -v grep | wc -l) -gt 0 ]; do
sleep 1
done

当然,在这种情况下,我需要将 & 附加到行尾!但我觉得这不是正确的做法。

那么我实际上如何将每 20 行组合在一起并等待它们完成,然后再转到接下来的 20 行,这个脚本是动态生成的,所以我可以在生成它的同时做任何我想做的数学运算,但它确实不必使用 wget,这只是一个示例,因此任何特定于 wget 的解决方案都不会对我有任何好处。

【问题讨论】:

wait 是这里的正确答案,但是您的 while [ $(ps … 最好写成 while pkill -0 $KEYWORD… - 使用 proctools...名称仍在运行。 我认为这个问题应该重新打开。 “可能重复”的 QA 就是并行运行 有限 个程序。像2-3个命令。然而,这个问题的重点是在例如运行命令。一个循环。 (见“但有 4000 行”)。 @VasyaNovikov 你有没有阅读 所有这个问题和副本的答案?此处对这个问题的每一个答案,也可以在重复问题的答案中找到。这正是重复问题的定义。无论您是否在循环中运行这些命令,都完全没有区别。 @robinCTS 有交叉点,但问题本身是不同的。此外,链接 QA 上最受欢迎的 6 个答案仅涉及 2 个流程。 我建议重新打开这个问题,因为它的答案比链接问题的答案更清晰、更清晰、更好,并且得到更高的评价,尽管它是三年前的。 【参考方案1】:

使用wait 内置:

process1 &
process2 &
process3 &
process4 &
wait
process5 &
process6 &
process7 &
process8 &
wait

对于上面的例子,4 个进程 process1 ... process4 会在后台启动,shell 会等到这些进程完成后再开始下一组。

来自GNU manual:

wait [jobspec or pid ...]

等到每个进程ID pid或作业规范jobspec指定的子进程退出,返回最后一个的退出状态 命令等待。如果给出了作业规范,则作业中的所有进程 正在等待。如果没有给出参数,所有当前活动的孩子 等待进程,返回状态为零。如果两者都没有 jobspec 和 pid 指定 shell 的一个活动子进程,即 返回状态为 127。

【讨论】:

所以基本上i=0; waitevery=4; for link in "$links[@]"; do wget "$link" & (( i++%waitevery==0 )) && wait; done >/dev/null 2>&1 除非您确定每个进程都将同时完成,否则这是个坏主意。您需要开始新的工作以将当前的总工作保持在一定的上限....parallel 就是答案。 有没有办法循环执行此操作? 我已经尝试过了,但似乎在一个块中完成的变量分配在下一个块中不可用。这是因为它们是独立的进程吗?有没有办法将变量传回主进程?【参考方案2】:

见parallel。它的语法类似于xargs,但它并行运行命令。

【讨论】:

这比使用wait 更好,因为它负责在旧作业完成时开始新作业,而不是等待整个批次完成后再开始下一个。 例如,如果你有一个文件中的链接列表,你可以做cat list_of_links.txt | parallel -j 4 wget ,这将保持四个wgets同时运行。 镇上有一个叫pexec的新孩子,是parallel的替代品。 提供一个例子会更有帮助 parallel --jobs 4 < list_of_commands.sh,其中 list_of_commands.sh 是一个文件,每行都有一个命令(例如wget LINK1,注意没有&)。之后可能需要执行CTRL+Zbg 以使其在后台运行。【参考方案3】:

你可以运行20个进程并使用命令:

wait

所有后台作业完成后,您的脚本将等待并继续。

【讨论】:

【参考方案4】:

事实上,xargs可以为你并行运行命令。有一个特殊的-P max_procs 命令行选项。见man xargs

【讨论】:

+100 这太棒了,因为它是内置的,使用非常简单,可以在单行中完成 非常适合用于小型容器,因为不需要额外的包/依赖项! 查看这个问题的例子:***.com/questions/28357997/…

以上是关于Bash 脚本并行处理有限数量的命令的主要内容,如果未能解决你的问题,请参考以下文章

如何找到理想数量的并行进程以使用 python 多处理运行?

用于并行运行 AWS Cli 命令以减少时间的 Bash 脚本

通过将命令行工具包装在带有 gnu 信号量的 bash 脚本中来并行化命令行工具

openMP:并行运行所有线程会导致内存不足异常

并行执行shell进程

使用 MPI 时并行 Eclipse 无法识别处理器的真实数量