并行化远程 tar 并通过 ssh 管道获取输出

并行化远程 tar 并通过 ssh 管道获取输出

我曾尝试并行化我正在使用的脚本,但到目前为止,GNU Parallel 非常具有挑战性。

我有 2 个文件 - 一个包含运行命令的主机,另一个包含命令的参数。以下是示例数据:

$ cat workers.host 
[email protected]
[email protected]
[email protected]
[email protected]



$ cat paths
/usr/local/jar/x/y/ jarxy
/usr/local/jar/z/y/ jarzy
/usr/local/jar/y/y/ jaryy
/usr/local/far/x/y/ farxy
/usr/local/jaz/z/z/ jazzz
/usr/local/mu/txt/ana/ acc01
/usr/local/jbr/x/y/ accxy

为了处理这个问题,我使用了以下脚本:

#!/bin/bash

echo "Run this on 192.168.130.10";

DATA=`date +%F`
DDAY=`date +%u`
DOMBAC='nice tar cpzf'

readarray -t hosts < workers.host

len=${#hosts[@]};
processed=0;

while read -r -a line; do

  let hostnum=processed%len;

  ssh ${hosts[$hostnum]} -i /root/.ssh/id_rsa "$DOMBAC - ${line[0]}" > "/data/backup/$DDAY/${line[1]}_${DATA}_FULL.tgz"

  let processed+=1;
done < paths

这种方法效果很好,但是需要在一台又一台机器上逐步处理。主机的性能非常强大,而网络在这里不是问题,所以我想尽可能地并行化。例如,在每个主机上运行 4 个 tar 命令实例,并通过 ssh 将输出传输到正确命名的文件中。我对并行完全迷茫了--results --sshloginfile……我最终试图实现的是让每个主机上运行 4 个作业,每个作业都有不同的参数(例如,主机 2 不会覆盖主机 1 已经执行的操作)。这可以在 GNU Parallel 中完成吗?

答案1

首先,您需要知道如何从一行输入中提取多个参数:

cat paths | parallel --colsep ' ' echo {2} == {1}

(我注意到一些 {2} 可以从 {1} 生成。如果总是如此,您可能需要研究 {= =};但那是另一个问题的故事)。

要远程运行作业,您可以使用-S

cat paths | parallel --colsep ' ' -S server echo {2} == {1}

要控制在远程服务器上运行的作业数,请使用-j

cat paths | parallel --colsep ' ' -j4 -S server echo {2} == {1}

要获取本地存储的输出,--return --cleanup可以使用:

cat paths | parallel --return {2} --cleanup --colsep ' ' -j4 -S server echo {2} == {1} '>' {2}

由于您希望将输出存储在本地的不同目录中,因此您需要使用 /./ 技巧:

cat paths | parallel --return my/local/dir/./{2} --cleanup --colsep ' ' -j4 -S server echo {2} == {1} '>' {2}

要使用特殊ssh命令,请使用--ssh

parallel --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return {2} --cleanup --colsep ' ' -j4 -S server echo {2} == {1} '>' {2}

要在多台服务器上运行,请--slf使用-S

parallel --slf hosts.txt --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return {2} --cleanup --colsep ' ' -j4 echo {2} == {1} '>' {2}

因此,你的命令总的来说可能如下所示:

parallel --slf hosts.txt --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return /data/backup/$DDAY/./{2}_${DATA}_FULL.tgz --cleanup --colsep ' ' -j4 "$DOMBAC - {1} > {2}_${DATA}_FULL.tgz"

答案2

您可以使用并行来实现这一点,但我认为这对于您要实现的目标来说有点过头了。相反,我只需使用后台作业来(几乎)同时运行这些命令。

为了在对现有脚本进行最少更改的情况下实现此目的,我们需要做的就是在每个任务运行时将其置于后台(使用 & 运算符执行此操作)。为了防止出现孤立进程,我们应该确保脚本在所有作业完成之前不会退出,这可以通过 bash 内置命令来实现wait。 jobs 命令将输出正在运行的任务列表(可能不是全部,根据执行时间,有些任务可能在您到达该位置之前已经完成)。

我也不确定为什么您要使用不带参数的 nice 命令 - 我相信如果没有参数,它所做的就是打印已启动任务的相对优先级,我想这可能是您的意图。

这是脚本的修改版本,包含以下更改

#!/bin/bash

echo "Run this on 192.168.130.10";

DATA=`date +%F`
DDAY=`date +%u`
DOMBAC='nice tar cpzf'

readarray -t hosts < workers.host

len=${#hosts[@]};
processed=0;

while read -r -a line; do

  let hostnum=processed%len;

  ssh ${hosts[$hostnum]} -i /root/.ssh/id_rsa "$DOMBAC - ${line[0]}" > "/data/backup/$DDAY/${line[1]}_${DATA}_FULL.tgz" &

  let processed+=1;
done < paths
jobs
wait

相关内容