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
,这将保持四个wget
s同时运行。
镇上有一个叫pexec的新孩子,是parallel
的替代品。
提供一个例子会更有帮助
parallel --jobs 4 < list_of_commands.sh
,其中 list_of_commands.sh 是一个文件,每行都有一个命令(例如wget LINK1
,注意没有&
)。之后可能需要执行CTRL+Z
和bg
以使其在后台运行。【参考方案3】:
你可以运行20个进程并使用命令:
wait
所有后台作业完成后,您的脚本将等待并继续。
【讨论】:
【参考方案4】:事实上,xargs
可以为你并行运行命令。有一个特殊的-P max_procs
命令行选项。见man xargs
。
【讨论】:
+100 这太棒了,因为它是内置的,使用非常简单,可以在单行中完成 非常适合用于小型容器,因为不需要额外的包/依赖项! 查看这个问题的例子:***.com/questions/28357997/…以上是关于Bash 脚本并行处理有限数量的命令的主要内容,如果未能解决你的问题,请参考以下文章
如何找到理想数量的并行进程以使用 python 多处理运行?
用于并行运行 AWS Cli 命令以减少时间的 Bash 脚本