你能用shell脚本制作一个进程池吗?

你能用shell脚本制作一个进程池吗?

假设我有大量作业(数十个或数百个)需要执行,但它们是 CPU 密集型的,并且只能同时运行几个作业。有没有一种简单的方法可以X立即运行作业并在完成后开始新的作业?我唯一能想到的是如下(伪代码):

jobs=(...);
MAX_JOBS=4;
cur_jobs=0;
pids=(); # hash/associative array
while (jobs); do
    while (cur_jobs < MAX_JOBS); do
        pop and spawn job and store PID and anything else needed;
        cur_jobs++;
    done
    sleep 5;
    for each PID:
        if no longer active; then
            remove PID;
            cur_jobs--;
done

我觉得我的解决方案过于复杂,就像我经常做的那样。目标系统是 FreeBSD,如果可能有某个端口可以完成所有艰苦的工作,但通用解决方案或通用习惯用法会更好。

答案1

如果你有 GNU Parallel,你可以这样做:

parallel do_it {} --option foo < argumentlist

GNU Parallel 是一个通用并行器,可以轻松地在同一台计算机或多台您可以通过 ssh 访问的计算机上并行运行作业。

如果您想要在 4 个 CPU 上运行 32 个不同的作业,则并行化的直接方法是在每个 CPU 上运行 8 个作业:

简单的调度

相反,GNU Parallel 在完成后会生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:

GNU 并行调度

安装

如果您的发行版未打包 GNU Parallel,您可以进行个人安装,不需要 root 访问权限。这样做可以在 10 秒内完成:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

对于其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README

了解更多

查看更多示例:http://www.gnu.org/software/parallel/man.html

观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

浏览本教程:http://www.gnu.org/software/parallel/parallel_tutorial.html

注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel

答案2

你可以,但它很棘手且脆弱。有多种选择,其中之一是xargs.

这篇有趣的文章讨论了依赖作业控制和信号时遇到的问题,确实值得推荐阅读:

http://prll.sourceforge.net/shell_parallel.html

这个人显然制作了一个新工具prll,可以并行执行任意 shell 函数(具有自动检测或用户定义的池大小),它使用同步所有输入和输出的控制进程。

在这里查看: https://gitorious.org/prll/pages/Home

答案3

我的情况与您完全相同,但我需要并行运行的作业是运行 ruby​​ 脚本的命令。首先我需要承认它并不完美,相反,它很脆弱。

我在 ruby​​ 代码中所做的是,

counting_process = IO.popen "ps -e | grep 'YourCMDPattern' -c"
count_of_processes = counting_process.readlines[0].to_i

然后在 while 循环中,我定期检查进程的计数,然后当计数低于我想要保留的并行执行数时,触发 shell 命令使用 ruby​​ 的 IO.popen 运行一定数量的新进程。

请注意,我需要运行的 shell 命令是动态的,并且包含从 ruby​​ 代码生成的变量,这就是为什么我必须在 ruby​​ 脚本中执行此操作。

如果不涉及 ruby​​,GNU Parallel 似乎是一个更好的选择。

相关内容