如何在 bash shell 脚本中一次复制三个文件而不是一次复制一个文件?

如何在 bash shell 脚本中一次复制三个文件而不是一次复制一个文件?

我正在运行我的 shell 脚本,该machineA脚本将文件machineB从.machineCmachineA

如果文件不存在于 中,那么它肯定machineB应该存在于 中。machineC因此,我将尝试首先复制文件machineB,如果它不存在,machineB那么我将去machineC复制相同的文件。

在这个文件夹里面machineB会有machineC一个这样的文件夹-YYYYMMDD

/data/pe_t1_snapshot

因此,无论日期是上述文件夹内这种格式的最新日期YYYYMMDD- 我都会选择该文件夹作为我需要开始复制文件的完整路径 -

20140317所以假设如果这是里面的最新日期文件夹/data/pe_t1_snapshot那么这将是我的完整路径 -

/data/pe_t1_snapshot/20140317

从我需要开始将文件复制到machineB和 的地方machineC。我需要复制from和400中的文件,每个文件大小为.machineAmachineBmachineC2.5 GB

早些时候,我尝试将文件逐一复制,machineA速度非常慢。有什么办法,我可以machineA在 bash shell 脚本中使用线程一次复制“三个”文件吗?

下面是我的 shell 脚本,它将文件一一复制到machineAfrommachineB和中machineC

#!/usr/bin/env bash

readonly PRIMARY=/export/home/david/dist/primary
readonly FILERS_LOCATION=(machineB machineC)
readonly MEMORY_MAPPED_LOCATION=/data/pe_t1_snapshot

PRIMARY_PARTITION=(0 548 272 4 544 276 8 556 280 12 552 284 16 256 564 20 260 560 24 264 572) # this will have more file numbers around 200

dir1=$(ssh -o "StrictHostKeyChecking no" david@${FILERS_LOCATION[0]} ls -dt1 "$MEMORY_MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
dir2=$(ssh -o "StrictHostKeyChecking no" david@${FILERS_LOCATION[1]} ls -dt1 "$MEMORY_MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)

## Build your list of filenames before the loop. 
for n in "${PRIMARY_PARTITION[@]}"
do
    primary_files="$primary_files :$dir1"/t1_weekly_1680_"$n"_200003_5.data
done

if [ "$dir1" = "$dir2" ]
then
    find "$PRIMARY" -mindepth 1 -delete
    rsync -avz david@${FILERS_LOCATION[0]}"${primary_files}" $PRIMARY/ 2>/dev/null
    rsync -avz david@${FILERS_LOCATION[1]}"${primary_files}" $PRIMARY/ 2>/dev/null
fi  

所以我在想,与其一次复制一个文件,为什么不一次复制“三个”文件,一旦这三个文件完成,我将移动到列表中的另外三个文件来同时复制?

我尝试打开三个 putty 实例,并同时从这三个实例复制一个文件。所有三个文件都在大约 50 秒内复制完成,所以这对我来说很快。由于这个原因,我尝试一次复制三个文件,而不是一次复制一个文件。

这可以吗?如果是,那么有人可以提供一个例子吗?我只是想尝试一下,看看效果如何。

@terdon 帮助我解决了上述问题,但我想尝试一次复制三个文件以查看它的行为方式。

更新:-

下面是上述 shell 脚本的简化版本。当我machineBmachineC.​它将尝试复制 中存在的文件号。machineAmachineAPRIMARY_PARTITION

#!/usr/bin/env bash

readonly PRIMARY=/export/home/david/dist/primary
readonly FILERS_LOCATION=(machineB machineC)
readonly MEMORY_MAPPED_LOCATION=/data/pe_t1_snapshot

PRIMARY_PARTITION=(0 548 272 4 544 276 8 556 280 12 552 284 16 256 564 20 260 560 24 264 572) # this will have more file numbers around 200

dir1=/data/pe_t1_snapshot/20140414
dir2=/data/pe_t1_snapshot/20140414

## Build your list of filenames before the loop. 
for n in "${PRIMARY_PARTITION[@]}"
do
    primary_files="$primary_files :$dir1"/t1_weekly_1680_"$n"_200003_5.data
done

if [ "$dir1" = "$dir2" ]
then
    # delete the files first and then copy it.
    find "$PRIMARY" -mindepth 1 -delete
    rsync -avz david@${FILERS_LOCATION[0]}"${primary_files}" $PRIMARY/
    rsync -avz david@${FILERS_LOCATION[1]}"${primary_files}" $PRIMARY/
fi

答案1

并行执行多个副本很少有用:无论限制因素是网络带宽还是磁盘带宽,您最终都会得到 N 个并行流,每个流的速度是 1/N 倍。

另一方面,当您从多个源(此处为 B 和 C)进行复制时,如果瓶颈位于 B 和 C 一侧(而不是在公共端)。所以你可以尝试并行进行副本:

rsync -avz david@${FILERS_LOCATION[0]}"${primary_files}" $PRIMARY/ &
rsync -avz david@${FILERS_LOCATION[1]}"${primary_files}" $PRIMARY/ &
wait

请注意,两个 rsync 命令的输出将混合在一起;您可能想将其发送到单独的文件中。

log_base=$(date +%Y%m%d-%H%M%S-$$)
rsync -avz david@${FILERS_LOCATION[0]}"${primary_files}" $PRIMARY/ >$log_base-B.log &
rsync -avz david@${FILERS_LOCATION[1]}"${primary_files}" $PRIMARY/ >$log_base-C.log &
wait

您在脚本中使用多个 SSH 连接到同一目标。建立 SSH 连接有不可避免的延迟。您可以通过保持连接打开并重新使用它来节省一些时间,这很容易,这要归功于主连接

答案2

您可以使用以下方法并行执行多项操作后台进程。作为一般示例:

rsync foo machine1: &
rsync bar machine2: &
rsync baz machine3: &
wait

确保wait程序的进展不会超出之前的那个点全部脚本创建的后台进程已完成。

位于&每个命令行的最末尾,因为;它就像一个命令分隔符。

相关内容