如何使 xargs 并行执行但一次显示单个实例的完整输出?

如何使 xargs 并行执行但一次显示单个实例的完整输出?

我正在远程主机上并行运行一些查询命令,xargs这些命令运行高效且非常好,但是在查找从哪个主机获取查询时遇到了一些问题。

现在,执行此操作的脚本部分看起来正是这样的:

export commands="cmd1; cmd2; "
hosts=("host1" "host2" "host3" "host4")
MaxInstance=10
echo_var(){
   echo "Executing in $1:"; sleep 1; echo "Output of: $commands"; return 0;
}
export -f echo_var
printf "%s\n" ${hosts[@]} | xargs -n 2 -P $MaxInstance -I {} $(command -v bash) -c 'echo_var "$1"' _ {}

输出结果应类似如下,因为sleep 1

Executing in host1:
Executing in host2:
Executing in host3:
Executing in host4:
Output of: cmd1; cmd2; 
Output of: cmd1; cmd2; 
Output of: cmd1; cmd2; 
Output of: cmd1; cmd2;

为了实现与最后显示的输出类似的输出,我必须将现有函数编辑为以下内容以更接近我想要的。但即使在这里我使用printf "%s\n%s" "$name" "$output",它有时也会在新行处中断。例如:

echo_var(){
 name="Executing in $1:"; sleep 1; output="Output of: $commands";
 echo -e "$name: $output" ## will work
 # echo -e "$name\n$output" ## will not work or even
 # printf "%s\n%s" "$name" "$output" ## will not work
 return 0;
}

在不牺牲并行执行速度的情况下,我希望得到如下输出。是否有任何选项xargs可以指定一次显示整个实例的输出?

Executing in host1:
Output of: cmd1; cmd2;
Executing in host2:
Output of: cmd1; cmd2;
Executing in host3:
Output of: cmd1; cmd2;
Executing in host4: 
Output of: cmd1; cmd2; 

答案1

见面GNU 并行sudo apt install parallel):

GNU parallel 确保命令的输出与您按顺序运行命令时的输出相同。
如果您现在使用 xargs 和 tee,您会发现 GNU parallel 非常易于使用,因为 GNU parallel 被编写为具有与 xargs 相同的选项。

我无法测试它,但在你的情况下,命令应该简单是:

parallel -n 2 -P $MaxInstance $(command -v bash) -c 'echo_var "$1"' _ {}

请注意,该moreutils软件包提供了parallel与 GNU parallel 不同的命令。

示例运行

此示例echo {} start; sleep 1; echo {} ready针对参数12和运行3,首先使用xargs,然后使用parallel

$ echo -e '1\n2\n3' | xargs -n1 -P3 -I{} bash -c 'echo {} start; sleep 1; echo {} ready'
2 start
1 start
3 start
2 ready
1 ready
3 ready
$ parallel 'echo {} start; sleep 1; echo {} ready' ::: 1 2 3
1 start
1 ready
2 start
2 ready
3 start
3 ready

当然,该echo |方法同样有效parallel,我只是喜欢上面显示的参数列表功能——它的作用完全相同。

parallel如果你因为没有预装、难以安装/更新或类似原因而犹豫不决,我强烈推荐该程序作者的博客文章不安装 GNU Parallel 的借口

相关内容