若是服务器之间须要保持某些文件的一致,咱们可使用scp
来复制,若是须要长期保持一致,能够配合crontab
脚原本使用。可是此时咱们有更优的方式,就是rsync+crontab
来实现定时增量传输保持文件一致。html
rsync
功能很强大,网上的资料也都很全,这里作一些简单的汇总。linux
rsync
原理这一小节内容大幅度转载了 RSYNC 的核心算法 的内容,由于原文章写的太好,就再也不狗尾续貂了,感兴趣的能够直接查看原文。他的翻译原文是: The rsync algorithm。
rsync
是linux
下同步文件的一个高效算法,用于同步更新两处计算机的文件和目录,并适当利用查找文件中的不一样块以减小数据传输。rsync
的主要特色就是增量传输,只对变动的部分进行传送。算法
假如咱们如今须要同步两个文件保持一致,而且只想传送不一样的部分,那么咱们就须要对两边的文件作diff
,可是这两个问题在两台不一样的机器上,没法作diff
。若是咱们作diff
,就要把一个文件传到另外一台机器上作diff
,但这样一来,咱们就传了整个文件,这与咱们只想传输不一样部的初衷相背。因而咱们就要想一个办法,让这两边的文件见不到面,但还能知道它们间有什么不一样。这就是rsync
的算法。shell
rsync
同步算法咱们将同步源文件名称为fileSrc
,同步目的文件叫fileDst
。数组
Checksum
算法首先,咱们会把fileDst
的文件平均切分红若干个小块,好比每块512
个字节(最后一块会小于这个数),而后对每块计算两个checksum
:服务器
rolling checksum
,是弱checksum
,32
位的checksum
checksum
,128
位的,之前用md4
,如今用md5 hash
算法。为何要这样?由于若干年前的硬件上跑md4
的算法太慢了,因此,咱们须要一个快算法来鉴别文件块的不一样,可是弱的adler32
算法碰撞几率过高了,因此咱们还要引入强的checksum
算法以保证两文件块是相同的。也就是说,弱的checksum
是用来区别不一样,而强的是用来确认相同。网络
同步目标端会把fileDst
的一个checksum
列表传给同步源,这个列表里包括了三个东西,rolling checksum(32bits),md5 checksume(128bits)
,文件块编号。数据结构
同步源机器拿到了这个列表后,会对fileSrc
作一样的checksum
,而后和fileDst
的checksum
作对比,这样就知道哪些文件块改变了。ssh
可是,聪明的你必定会有如下两个疑问:工具
若是我fileSrc
这边在文件中间加了一个字符,这样后面的文件块都会位移一个字符,这样就彻底和fileDst
这边的不同了,但理论上来讲,我应该只须要传一个字符就行了。这个怎么解决?
若是这个checksum
列表特别长,而个人两边的相同的文件块可能并非同样的顺序,那就须要查找,线性的查找起来应该特别慢吧。这个怎么解决?
很好,让咱们来看一下同步源端的算法。
checksum
查找算法同步源端拿到fileDst
的checksum
数组后,会把这个数据存到一个hash table
(特殊的数据结构体,能够快速检索)中,用rolling checksum
作hash
,以便得到O(1)
时间复杂度的查找性能。这个hash table
是16bits
的,因此,hash table
的尺寸是2的16次方
,对rolling checksum
的hash
会被散列到0 到 2^16 – 1
中的某个整数值。
fileSrc
的第一个文件块(咱们假设的是512
个长度),也就是从fileSrc
的第1
个字节到第512
个字节,取出来后作rolling checksum
计算。计算好的值到hash
表中查。fileDst
中有潜在相同的文件块,因而就再比较md5
的checksum
,由于rolling checksume
太弱了,可能发生碰撞。因而还要算md5
的128bits
的checksum
,这样一来,咱们就有 2^-(32+128) = 2^-160
的几率发生碰撞,这过小了能够忽略。若是rolling checksum
和md5 checksum
都相同,这说明在fileDst
中有相同的块,咱们须要记下这一块在fileDst
下的文件编号。fileSrc
的rolling checksum
没有在hash table
中找到,那就不用算md5 checksum
了。表示这一块中有不一样的信息。总之,只要rolling checksum
或 md5 checksum
其中有一个在fileDst
的checksum hash
表中找不到匹配项,那么就会触发算法对fileSrc
的rolling
动做。因而,算法会住后step 1
个字节,取fileSrc
中字节2-513
的文件块要作checksum,go to (1.)
– 如今你明白什么叫rolling checksum
了吧。fileSrc
相邻两次匹配中的那些文本字符,这些就是咱们要往同步目标端传的文件内容了。
最终在同步源这端,咱们的rsync
算法可能会获得这个样子的一个数据数组,图中,红色块表示在目标端已匹配上,不用传输(注:我专门在其中显示了两块chunk #5
,表明数据中有复制的地方,不用传输),而白色的地方就是须要传输的内容(注意:这些白色的块是不定长的),这样,同步源这端把这个数组(白色的就是实际内容,红色的就放一个标号)压缩传到目的端,在目的端的rsync
会根据这个表从新生成文件,这样,同步完成。
最后想说一下,对于某些压缩文件使用rsync
传输可能会传得更多,由于被压缩后的文件可能会很是的不一样。对此,对于gzip
和bzip2
这样的命令,记得开启 “rsyncalbe”
模式。
rsync
的使用一样的,这一小节内容也是大幅度转载了 第2章 rsync(一):基本命令和用法 的内容,由于原文章很全面,感兴趣的能够直接查看原文。
rsync
是实现增量备份的工具。配合任务计划,rsync
能实现定时或间隔同步,配合inotify
或sersync
,能够实现触发式的实时同步。它的目的是实现本地主机和远程主机上的文件同步(包括本地推到远程,远程拉到本地两种同步方式),也能够实现本地不一样路径下文件的同步,但不能实现远程路径1
到远程路径2
之间的同步(scp
能够实现)。
rsync
同步过程当中由两部分组成:决定哪些文件须要同步的检查模式以及文件同步时的同步模式。
rsync
使用"quick check"
算法快速检查源文件和目标文件的大小、mtime
(修改时间)是否一致,若是不一致则须要传输。固然,也能够经过在rsync
命令行中指定某些选项来改变quick check
的检查模式,好比"--size-only"
选项表示"quick check"
将仅检查文件大小不一样的文件做为待传输文件。rsync
支持很是多的选项,其中检查模式的自定义性是很是有弹性的。rsync
也提供很是多的选项使得同步模式变得更具弹性。相对来讲,为rsync
手动指定同步模式的选项更常见一些,只有在有特殊需求时才指定检查模式,由于大多数检查模式选项均可能会影响rsync
的性能。
rsync
四种工做方式rsync
的基础语法为:rsync [OPTION...] SRC... [DEST]
支持的参数高达一百多个,最经常使用的选项组合是"avz"
,即压缩和显示部分信息,并以归档模式传输。详细的能够参考 博客园-man rsync翻译(rsync命令中文手册),下面是部分参数说明:
-v:显示rsync过程当中详细信息。可使用"-vvvv"获取更详细信息。 -P:显示文件传输的进度信息。(实际上"-P"="--partial --progress",其中的"--progress"才是显示进度信息的)。 -n --dry-run :仅测试传输,而不实际传输。常和"-vvvv"配合使用来查看rsync是如何工做的。 -a --archive :归档模式,表示递归传输并保持文件属性。等同于"-rtopgDl"。 -r --recursive:递归到目录中去。 -t --times:保持mtime属性。强烈建议任什么时候候都加上"-t",不然目标文件mtime会设置为系统时间,致使下次更新 :检查出mtime不一样从而致使增量传输无效。 -o --owner:保持owner属性(属主)。 -g --group:保持group属性(属组)。 -p --perms:保持perms属性(权限,不包括特殊权限)。 -D :是"--device --specials"选项的组合,即也拷贝设备文件和特殊文件。 -l --links:若是文件是软连接文件,则拷贝软连接自己而非软连接所指向的对象。 -z :传输时进行压缩提升效率。 -R --relative:使用相对路径。意味着将命令行中指定的全路径而非路径最尾部的文件名发送给服务端,包括它们的属性。用法见下文示例。 --size-only :默认算法是检查文件大小和mtime不一样的文件,使用此选项将只检查文件大小。 -u --update :仅在源mtime比目标已存在文件的mtime新时才拷贝。注意,该选项是接收端判断的,不会影响删除行为。 -d --dirs :以不递归的方式拷贝目录自己。默认递归时,若是源为"dir1/file1",则不会拷贝dir1目录,使用该选项将拷贝dir1但不拷贝file1。 --max-size :限制rsync传输的最大文件大小。可使用单位后缀,还能够是一个小数值(例如:"--max-size=1.5m") --min-size :限制rsync传输的最小文件大小。这能够用于禁止传输小文件或那些垃圾文件。 --exclude :指定排除规则来排除不须要传输的文件。 --delete :以SRC为主,对DEST进行同步。多则删之,少则补之。注意"--delete"是在接收端执行的,因此它是在 :exclude/include规则生效以后才执行的。 -b --backup :对目标上已存在的文件作一个备份,备份的文件名后默认使用"~"作后缀。 --backup-dir:指定备份文件的保存路径。不指定时默认和待备份文件保存在同一目录下。 -e :指定所要使用的远程shell程序,默认为ssh。 --port :链接daemon时使用的端口号,默认为873端口。 --password-file:daemon模式时的密码文件,能够从中读取密码实现非交互式。注意,这不是远程shell认证的密码,而是rsync模块认证的密码。 -W --whole-file:rsync将再也不使用增量传输,而是全量传输。在网络带宽高于磁盘带宽时,该选项比增量传输更高效。 --existing :要求只更新目标端已存在的文件,目标端还不存在的文件不传输。注意,使用相对路径时若是上层目录不存在也不会传输。 --ignore-existing:要求只更新目标端不存在的文件。和"--existing"结合使用有特殊功能,见下文示例。 --remove-source-files:要求删除源端已经成功传输的文件。
rsync [OPTION...] SRC... [DEST]
shell
和远程主机通讯Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST] Push: rsync [OPTION...] SRC... [USER@]HOST:DEST
rsync daemon
Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST] rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST] Push: rsync [OPTION...] SRC... [USER@]HOST::DEST rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
前二者的本质是经过管道通讯,即便是远程shell
。而方式(3)
则是让远程主机上运行rsync
服务,使其监听在一个端口上,等待客户端的链接。
路径的格式能够是本地路径,也能够是使用user@host:path
或user@host::path
的远程路径,若是主机和path
路径之间使用单个冒号隔开,表示使用的是远程shell
通讯方式,而使用双冒号隔开的则表示的是链接rsync daemon
。另外,链接rsync daemon
时,还提供了URL
格式的路径表述方式rsync://user@host/path
。
shell
临时启动一个rsync daemon
rsync [options] --rsh=ssh auth_user@host::module rsync [options] --rsh="ssh -l ssh_user" auth_user@host::module rsync [options] -e "ssh -l ssh_user" auth_user@host::module rsync [options] -e "ssh -l ssh_user" rsync://auth_user@host/module
这不一样于方式(3)
,它不要求远程主机上事先启动rsync
服务,而是临时派生出rsync daemon
,它是单用途的一次性daemon
,仅用于临时读取daemon
的配置文件,当这次rsync
同步完成,远程shell
启动的rsync daemon
进程也会自动消逝。此通讯方式的命令行语法格式同"Access via rsync daemon"
,但要求options
部分必须明确指定"--rsh"
选项或其短选项"-e"
。
# 将/etc/fstab拷贝到/tmp目录下 rsync /etc/fstab /tmp # 将/etc/cron.d目录拷贝到/tmp下 rsync -r /etc/cron.d /tmp # 将/etc/cron.d目录拷贝到/tmp下,但要求在/tmp下也生成etc子目 rsync -R -r /etc/cron.d /tmp # 拷贝源路径较长,但只保留一部分目录结构,使用一个点表明相对路径的起始位置 rsync -R -r /var/./log/anaconda /tmp # 对远程目录下已存在文件作备份,备份后缀为"~",使用"--suffix"指定后缀 rsync -R -r --backup /var/./log/anaconda /tmp # 指定备份文件保存路径,默认将不会加备份后缀,使用"--suffix"显式指定后缀 rsync -R -r --backup --backup-dir=/tmp/log_back /var/./log/anaconda /tmp # .指定ssh链接参数,如端口、链接的用户、ssh选项等 rsync -e "ssh -p 22 -o StrictHostKeyChecking=no" /etc/fstab 172.16.10.5:/tmp # 使用"--existing"选项使得只更新目标端已存在的文件 rsync -r -v --existing /tmp/a/ /tmp/b # "--ignore-existing"更新目标端不存在的文件 rsync -r -v --ignore-existing /tmp/a/ /tmp/b # "--remove-source-files"删除源端文件 rsync -r -v --remove-source-files /tmp/a/anaconda /tmp/a/audit /tmp # 使用"--exclude"选项指定排除规则,排除那些不须要传输的文件。 rsync -r -v --exclude="anaconda/*.log" /var/log/anaconda /var/log/audit /tmp
若是仅有一个SRC
或DEST
参数,则将以相似于"ls -l"
的方式列出源文件列表(只有一个路径参数,总会认为是源文件),而不是复制文件。
源路径若是是一个目录的话,带上尾随斜线和不带尾随斜线是不同的,不带尾随斜线表示的是整个目录包括目录自己,带上尾随斜线表示的是目录中的文件,不包括目录自己。
# 在/tmp目录下建立etc目录 [root@xuexi ~]# rsync -a /etc /tmp # 不会在/tmp目录下建立etc目录,源路径/etc/中的全部文件都直接放在/tmp目录下 [root@xuexi ~]# rsync -a /etc/ /tmp