我正在运行我的 shell 脚本,该machineA
脚本将文件machineB
从.machineC
machineA
如果文件不存在于 中,那么它肯定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
中的文件,每个文件大小为.machineA
machineB
machineC
2.5 GB
早些时候,我尝试将文件逐一复制,machineA
速度非常慢。有什么办法,我可以machineA
在 bash shell 脚本中使用线程一次复制“三个”文件吗?
下面是我的 shell 脚本,它将文件一一复制到machineA
frommachineB
和中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 脚本的简化版本。当我machineB
在machineC
.它将尝试复制 中存在的文件号。machineA
machineA
PRIMARY_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
程序的进展不会超出之前的那个点全部脚本创建的后台进程已完成。
位于&
每个命令行的最末尾,因为;
它就像一个命令分隔符。