首页 > 解决方案 > bash循环的多处理

问题描述

我有一个非平凡的 Bash 脚本,大致采用以下形式:

# Initialization

<generate_data> | while read line; do

    # Run tests and filters on line

    if [ "$tests_pass" ]; then
        echo "$filtered_line"
    fi

done | sort <sort_option> | <consume_data>

# Finalization

与过滤器相比,生成器消耗的处理资源最少,当然,在所有过滤数据都可用之前,排序操作无法开始。因此,过滤器,由几个循环和条件组成的级联用 Bash 原生编写,是处理瓶颈,运行此循环的单个进程会消耗整个核心。

一个有用的目标是将这个逻辑分布在几个子进程中,每个子进程都运行单独的过滤器循环,而这些子进程又会消耗来自生成器的行块,并且每个子进程都会产生连接到排序操作中的输出块。此类功能可通过 GNU Parallel 等工具获得,但使用它们需要调用外部命令才能在管道中运行。

是否有任何方便的工具或功能可以使脚本上的操作可以分布在多个进程中,而不会破坏脚本的整体结构?我不知道 Bash 内置功能,但肯定会有用。

标签: bashshellmultiprocessing

解决方案


调用外部命令的问题是在将过滤器逻辑移动到可以独立调用的某些命令方面缺乏代码可管理性。

如果这就是不使用 GNU Parallel 的原因,那听起来你好像不知道parallel --embed.

--embed正是因为人们需要将 GNU Parallel 放在与其余代码相同的文件中。

[output from parallel --embed]

myfilter() {
    while read line; do
      # Run tests and filters on line
      if [ "$tests_pass" ]; then
        echo "$filtered_line"
      fi
    done
}   
export -f myfilter

<generate_data> | parallel --pipe myfilter | sort <sort_option> | <consume_data>

即使未安装 GNU Parallel,生成的脚本也会运行。


推荐阅读