GNU Parallel 的使用 - 如何将当前传递的字符串并行化?

GNU Parallel 的使用 - 如何将当前传递的字符串并行化?

我正在使用 GNU parallel,并且想了解 - 如何获取传递给每个并行命令的单独字符串?

举个例子,GNU Parallel 文档显示如何将文件从当前目录移动到另一个目录:

ls | parallel mv {} destdir

那么有没有办法可以单独获取/打印传递给并行的每个文件?

并行处理案例

我需要并行处理检查多个站点并记录

  • http 返回代码(2xx、4xx、5xx)
  • 源 URL
  • 最终目标 URL
  • curl 退出代码

以下是实现该功能的代码:

    unset return_code_array
    unset destination_url_array
    unset exit_code_array

    while read -r return_code_var destination_url_var exit_code_var; do

        destination_url_array+=("$destination_url_var")
        exit_code_array+=("$exit_code_var")
        return_code_array+=("$return_code_var")

    done < <(printf '%s\n' "${all_valid_URLs_array[@]}" | parallel -j 20 -k 'curl --max-time 20 -sL -o /dev/null -w "%{response_code} %{url_effective} " {}; printf "%s %s\n" "$?" ')

因此,我有三个数组,它们保存了 HTTP 返回代码、最终目标 URL 以及条目对应行的 curl 退出代码状态all_valid_URLs_array。同时,我需要对每个数组进行一些处理destination_url_var- 例如比较它是否与源 URL 匹配,但不知道如何获取传递给 parallels 的字符串。

目前,我正在进行上述循环之后的第二个循环以进行此类处理,但想知道是否可以完成。

谢谢。

答案1

在您的示例中'curl … {}; printf "%s %s\n" "$?" '(为什么是第二个%s?)是一段单引号的 shell 代码。在其中您可以{}多次使用:

curl … {}; printf "%s %s\n" "$?" {}

或者创建一个变量并根据需要多次使用它。变量的名称可以是描述性的,这是一个优点。还有另一个优点:通常替换的内容可能{}是一个长字符串,多次替换可能会使传递给特定 shell 的代码膨胀parallel。在我看来,最好替换一次,让 shell 保存字符串并重复使用它:

source_URL={}; curl … "$source_URL"; printf "%s %s\n" "$?" "$source_URL"

对于 GNU 来说,parallel嵌入到 shell 代码中是安全的{}。这是此答案中明确提到的例外:切勿嵌入{}shell 代码!。你可能已经知道这一点,这句话是针对一般观众的。

注意你需要在主循环中调整read,它现在必须读入变量。这样,您就可以将源 URL 从内部传输parallel到主循环,您可以在主循环中将其进行比较destination_url_var或执行任何您想要的操作。

在这种方法中,“任何你想要的”仍然无法并行化。

curl如果你捕获了shell 代码运行的输出并将其分离到其中的变量中parallel(而不是仅仅将其打印出来并在其外部捕获parallel),那么你将能够进行比较(或者任何你想要的)那里,并行。例如printf 有条件的。在何处实现所需的逻辑由您决定,只要 的内部parallel以外部所期望的形式生成输出即可read

传递给的 shell 代码parallel仍然需要用单引号引起来。随着代码的增长,您可能需要在此代码中使用(嵌入)单引号;这样引用就会变得有些复杂,可读性也会降低。在这种情况下,请考虑将代码移至单独的脚本,您可以在其中独立引用。您将从主脚本中调用它,如下所示:

while read … ; done < <( … | parallel -j 20 -k 'path/to/separate_script {}' )

在里面separate_script替换的字符串{}将作为$1(不要忘记双引号)。

相关内容