Bash 通过同步/并发文件传输加快rsync?

Bash 通过同步/并发文件传输加快rsync?,bash,shell,ubuntu-12.04,rsync,simultaneous,Bash,Shell,Ubuntu 12.04,Rsync,Simultaneous,我们需要尽快将15TB的数据从一台服务器传输到另一台服务器。我们目前使用的是rsync,但当我们的网络能够900+Mb/s(使用iperf进行测试)时,我们只能获得大约150Mb/s的速度。我已经对磁盘、网络等进行了测试,结果发现rsync一次只传输一个文件,这导致了速度减慢 我找到了一个脚本,可以为目录树中的每个文件夹运行不同的rsync(允许您限制为x个),但我无法让它工作,它仍然一次只运行一个rsync 我找到了脚本(复制如下) 我们的目录树如下所示: /main - /files

我们需要尽快将
15TB的数据从一台服务器传输到另一台服务器。我们目前使用的是
rsync
,但当我们的网络能够
900+Mb/s
(使用
iperf
进行测试)时,我们只能获得大约
150Mb/s的速度。我已经对磁盘、网络等进行了测试,结果发现rsync一次只传输一个文件,这导致了速度减慢

我找到了一个脚本,可以为目录树中的每个文件夹运行不同的rsync(允许您限制为x个),但我无法让它工作,它仍然一次只运行一个rsync

我找到了
脚本
(复制如下)

我们的目录树如下所示:

/main
   - /files
      - /1
         - 343
            - 123.wav
            - 76.wav
         - 772
            - 122.wav
         - 55
            - 555.wav
            - 324.wav
            - 1209.wav
         - 43
            - 999.wav
            - 111.wav
            - 222.wav
      - /2
         - 346
            - 9993.wav
         - 4242
            - 827.wav
      - /3
         - 2545
            - 76.wav
            - 199.wav
            - 183.wav
         - 23
            - 33.wav
            - 876.wav
         - 4256
            - 998.wav
            - 1665.wav
            - 332.wav
            - 112.wav
            - 5584.wav
所以我希望为/main/files中的每个目录创建一个rsync,一次最多创建5个。因此,在本例中,将运行3个rsync,用于
/main/files/1
/main/files/2
/main/files/3

我试过这样做,但它只为
/main/files/2
文件夹一次运行1个rsync:

#!/bin/bash

# Define source, target, maxdepth and cd to source
source="/main/files"
target="/main/filesTest"
depth=1
cd "${source}"

# Set the maximum number of concurrent rsync threads
maxthreads=5
# How long to wait before checking the number of rsync threads again
sleeptime=5

# Find all folders in the source directory within the maxdepth level
find . -maxdepth ${depth} -type d | while read dir
do
    # Make sure to ignore the parent folder
    if [ `echo "${dir}" | awk -F'/' '{print NF}'` -gt ${depth} ]
    then
        # Strip leading dot slash
        subfolder=$(echo "${dir}" | sed 's@^\./@@g')
        if [ ! -d "${target}/${subfolder}" ]
        then
            # Create destination folder and set ownership and permissions to match source
            mkdir -p "${target}/${subfolder}"
            chown --reference="${source}/${subfolder}" "${target}/${subfolder}"
            chmod --reference="${source}/${subfolder}" "${target}/${subfolder}"
        fi
        # Make sure the number of rsync threads running is below the threshold
        while [ `ps -ef | grep -c [r]sync` -gt ${maxthreads} ]
        do
            echo "Sleeping ${sleeptime} seconds"
            sleep ${sleeptime}
        done
        # Run rsync in background for the current subfolder and move one to the next one
        nohup rsync -a "${source}/${subfolder}/" "${target}/${subfolder}/" </dev/null >/dev/null 2>&1 &
    fi
done

# Find all files above the maxdepth level and rsync them as well
find . -maxdepth ${depth} -type f -print0 | rsync -a --files-from=- --from0 ./ "${target}/"
#/bin/bash
#定义源、目标、maxdepth和cd到源
source=“/main/files”
target=“/main/filesTest”
深度=1
cd“${source}”
#设置最大并发rsync线程数
maxthreads=5
#在再次检查rsync线程数之前需要等待多长时间
睡眠时间=5
#查找maxdepth级别内源目录中的所有文件夹
找到-maxdepth${depth}-在读取目录时键入d |
做
#确保忽略父文件夹
如果[`echo“${dir}”| awk-F'/''{print NF}'`-gt${depth}]
然后
#带前导点斜线
子文件夹=$(回显“${dir}”sed's@^\./@@g')
如果[!-d“${target}/${subfolder}”]
然后
#创建目标文件夹并设置所有权和权限以匹配源
mkdir-p“${target}/${subfolder}”
chown--reference=“${source}/${subfolder}”“${target}/${subfolder}”
chmod--reference=“${source}/${subfolder}”“${target}/${subfolder}”
fi
#确保正在运行的rsync线程数低于阈值
而[`ps-ef | grep-c[r]sync`-gt${maxthreads}]
做
回显“睡眠${sleeptime}秒”
睡眠${sleeptime}
完成
#在后台为当前子文件夹运行rsync,并将其中一个子文件夹移动到下一个子文件夹
nohup rsync-a“${source}/${subfolder}/”“${target}/${subfolder}/”/dev/null 2>&1&
fi
完成
#查找maxdepth级别以上的所有文件,并对其进行rsync
找到-maxdepth${depth}-type f-print0 | rsync-a--files from=--from0./“${target}/”

rsync
通过网络尽可能快地传输文件。例如,尝试使用它复制一个目标上根本不存在的大文件。该速度是rsync传输数据的最大速度。将其与
scp
的速度进行比较(例如)<当目标文件存在时,code>rsync
在原始传输时甚至更慢,因为双方都必须就文件的哪些部分被更改进行双向聊天,但通过识别不需要传输的数据来为自己付费

并行运行
rsync
的一种更简单的方法是使用。下面的命令最多可并行运行5个rsync,每个命令复制一个目录。请注意,瓶颈可能不是您的网络,但CPU和磁盘的速度以及并行运行只会使它们变得更慢,而不是更快

run_rsync() {
    # e.g. copies /main/files/blah to /main/filesTest/blah
    rsync -av "$1" "/main/filesTest/${1#/main/files/}"
}
export -f run_rsync
parallel -j5 run_rsync ::: /main/files/*
更新答案(2020年1月)

xargs
现在是实现并行执行的推荐工具。几乎所有地方都预装了它。对于运行多个
rsync
任务,命令如下:

ls /srv/mail | xargs -n1 -P4 -I% rsync -Pa % myserver.com:/srv/mail/
这将列出
/srv/mail
中的所有文件夹,将它们传送到
xargs
,xargs将逐个读取它们,并一次运行4个
rsync
进程。
%
字符替换每个命令调用的输入参数

使用
并行的原始答案

ls /srv/mail | parallel -v -j8 rsync -raz --progress {} myserver.com:/srv/mail/{}

网络上列出了许多可供选择的工具和方法。例如:

  • 描述了使用
    xargs
    find
    并行化rsync,而无需为大多数*nix系统安装任何新软件

  • 并为并行rsync提供了功能丰富的Perl包装器


我开发了一个名为:parallel\u sync的python包

下面是如何使用它的示例代码:

from parallel_sync import rsync
creds = {'user': 'myusername', 'key':'~/.ssh/id_rsa', 'host':'192.168.16.31'}
rsync.upload('/tmp/local_dir', '/tmp/remote_dir', creds=creds)
并行度默认为10;您可以增加它:

from parallel_sync import rsync
creds = {'user': 'myusername', 'key':'~/.ssh/id_rsa', 'host':'192.168.16.31'}
rsync.upload('/tmp/local_dir', '/tmp/remote_dir', creds=creds, parallelism=20)

但是请注意,ssh通常默认将MaxSessions设置为10,因此要将其增加到10以上,您必须修改ssh设置。

您可以使用支持一次运行多个进程的
xargs
。对于您的情况,它将是:

ls -1 /main/files | xargs -I {} -P 5 -n 1 rsync -avh /main/files/{} /main/filesTest/

我发现最简单的方法是在shell中使用后台作业:

for d in /main/files/*; do
    rsync -a "$d" remote:/main/files/ &
done
当心它并没有限制工作的数量!如果您是网络绑定的,这并不是一个真正的问题,但如果您等待旋转生锈,这将打击磁盘

你可以加上

while [ $(jobs | wc -l | xargs) -gt 10 ]; do sleep 1; done
在循环内进行基本形式的作业控制。

您是否尝试过使用

使用
rclone
可以执行以下操作

rclone copy "${source}/${subfolder}/" "${target}/${subfolder}/" --progress --multi-thread-streams=N

其中,
--multi-thread streams=N
表示您希望生成的线程数。

我找到的最短版本是使用
--cat
并行
选项,如下所示。此版本避免使用xargs,仅依赖于
parallel
的功能:

ls /srv/mail | parallel -v -j8 rsync -raz --progress {} myserver.com:/srv/mail/{}
cat files.txt |\
parallel-n500--lb--pipe--cat rsync--files from={}user@remote:/dir/dir-avPi
####Arg解释者
#-n 500::将输入拆分为500个条目的块
#
#--cat::创建一个由{}引用的tmp文件,其中包含
#每个专业选手的参赛内容