rsync是linux下同步文件的一个高效算法,用于同步更新两处计算机的文件和目录,并适当利用查找文件中的不一样块以减小数据传输。rsync的主要特色就是增量传输,只对变动的部分进行传送。html
假如咱们如今须要同步两个文件保持一致,而且只想传送不一样的部分,那么咱们就须要对两边的文件作diff,可是这两个问题在两台不一样的机器上,没法作diff。若是咱们作diff,就要把一个文件传到另外一台机器上作diff,但这样一来,咱们就传了整个文件,这与咱们只想传输不一样部的初衷相背。因而咱们就要想一个办法,让这两边的文件见不到面,但还能知道它们间有什么不一样。这就是rsync的算法。
咱们将同步源文件名称为fileSrc,同步目的文件叫fileDst。linux
首先,咱们会把fileDst的文件平均切分红若干个小块,好比每块512个字节(最后一块会小于这个数),而后对每块计算两个checksum:算法
一个叫rolling checksum,是弱checksum,32位的checksum
另外一个是强checksum,128位的,之前用md4,如今用md5 hash算法。
为何要这样?由于若干年前的硬件上跑md4的算法太慢了,因此,咱们须要一个快算法来鉴别文件块的不一样,可是弱的adler32算法碰撞几率过高了,因此咱们还要引入强的checksum算法以保证两文件块是相同的。也就是说,弱的checksum是用来区别不一样,而强的是用来确认相同。shell
同步目标端会把fileDst的一个checksum列表传给同步源,这个列表里包括了三个东西,rolling checksum(32bits),md5 checksume(128bits),文件块编号。数组
同步源机器拿到了这个列表后,会对fileSrc作一样的checksum,而后和fileDst的checksum作对比,这样就知道哪些文件块改变了。
可是,若是我fileSrc这边在文件中间加了一个字符,这样后面的文件块都会位移一个字符,这样就彻底和fileDst这边的不同了,但理论上来讲,我应该只须要传一个字符就行了。这个怎么解决? 若是这个checksum列表特别长,而个人两边的相同的文件块可能并非同样的顺序,那就须要查找,线性的查找起来应该特别慢吧。这个怎么解决? 很好,让咱们来看一下同步源端的算法。网络
同步源端拿到fileDst的checksum数组后,会把这个数据存到一个hash table(特殊的数据结构体,能够快速检索)中,用rolling checksum作hash,以便得到O(1)时间复杂度的查找性能。这个hash table是16bits的,因此,hash table的尺寸是2的16次方,对rolling checksum的hash会被散列到0 到 2^16 – 1中的某个整数值。数据结构
最终在同步源这端,咱们的rsync算法可能会获得这个样子的一个数据数组,同步源这端把这个数组位置和数据压缩传到目的端,在目的端的rsync会根据这个表从新生成文件,这样,同步完成。ssh
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 [OPTION...] SRC... [DEST]
rsync支持的参数高达一百多个,最经常使用的选项组合是"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 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