我正在使用 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
(不要忘记双引号)。