备份工具rsync

rsync是Linux系统下最具代表性的数据备份工具,它具有以下特点:

  • 不仅可以远程同步,还可以在本地进行同步。
  • 增量更新,减少同步的流量。
  • 可以在windows和mac下使用,能够做到跨平台使用。
  • 可以很容易做到保持原来文件的权限、时间、软硬链接等等。
  • 比较安全,可以使用scp、ssh等方式来传输文件,当然也可以通过直接的socket连接。

rsync的命令格式

rsync命令的格式是:rsync [OPTION]... SRC DEST;其中,SRC和DEST既可以取本地目录/文件,也可以取远程目录/文件,如rsync [OPTION]... SRC [USER@]HOST:DESTrsync [OPTION]... SRC [USER@]HOST::DEST

SRC可以由多个文件组成,以此来实现一次性指定同步多个文件:rsync [OPTION]... SRC1 SRC2 SRC3 DEST

rsync的常用参数

  • -a:归档模式,表示以递归方式传输文件,并保持所有属性,它等同于-rlptgoD,这是最常用的参数。另外,为灵活起见,-a后可跟一个--no-OPTION来表示关闭-rlptgoD中的任意一个参数,比如-a--no-l等同于-rptgoD
  • -r:表示以递归模式处理子目录。
  • -v:表示打印同步的汇总结果信息。
  • -l:表示保留软连接。
  • -L:表示如果SRC中含有软连接文件,则取其指向的目标文件同步到DEST(当然软连接就不会同步过去了)。
  • —delete:表示删除DST中SRC没有的文件。
  • —exclude=PATTERN:表示指定排除不需要传输的文件。
  • —progress:表示动态打印rsync同步过程中的状态以及最后的汇总结果信息(即包含了-V的效果)。
  • -z:表示将会在同步传输过程中压缩。

rsync远程同步

虽然rsync可以在本地的两个目录中进行同步,但其实rsync更常见的应用场景应该是在两台机器中进行远程同步(不论是通过局域网还是互联网)。

通过ssh的方式进行远程同步

其命令格式(注意是只有一个冒号)如下:

  • rsync [OPTION]... SRC [USER@]HOST:DEST
  • rsync [OPTION]... [USER@]HOST:SRC DEST

在输入命令后,接下来的事情其实跟openssh的反馈十分类似:如没有通过密钥认证,则需要输入密码进行认证。认证通过后,接下来的rsync执行结果就跟在本地同步操作的没有两样了。

通过rsync后台服务(rsyncd)的方式进行远程同步

这种方式的原理是在远程服务器上建立rsync服务器,并将本机看成是rsync客户端,这样我们就可以利用rsync客户端远程连接(via TCP)rsync服务器进行远程同步的操作了。

下面我们分服务器端客户端两个部分来解释通过rsync后台服务(rsyncd)的方式进行远程同步的整个过程。

服务器端
rsync配置文件

启动rsync后台服务rsyncd前,我们需要先准备一份rsyncd的配置文件——/etc/rsyncd.conf,该配置可控制rsync的权限、可操作范围、日志、可用模块等方方面面的内容。

配置文件由两个部分组成:全局变量和模块变量,但你也可以把模块变量写在全局变量里,作为模块变量的一份默认值。

下面列出一些常用的变量,具体的变量列表请查询官方文档

  • 全局变量
    • pid file:指定pid文件路径(记录rsyncd的进程ID) 。
    • port:指定监听哪个端口,默认是873端口。
    • address:指定启动服务的IP,假如你的服务器有多个IP,那么可以指定其中的一个IP来启动rsyncd服务;如果不指定则默认在全部IP上启动
  • 模块变量
    • path:指定该模块的根目录,客户端在访问该模块时不能超出该根目录的层级范围。另外,此变量可以达成某些骚操作,比如path=/home/%RSYNC_USER_NAME%,则当连接服务器端的rsync用户名为test时,该模块的根目录就自动设置为/home/test,但为了安全起见,不推荐这么干。
    • use chroot:值取truefalse,表示在传输文件前,首先chrootpath参数所指定的目录下,这样做可以获得额外的安全防护;但是缺点是需要以root权限来启动rsyncd,并且,如果同步的内容里有软连接指向模块根目录以外的文件,则不能实现同步。
    • max connections:指定该模块最大的连接数,如果有超出此最大连接数的客户端试图连接,则会被告知try later;该值默认为0,即没有限制最大连接数。
    • log file:指定日志文件的路径,默认使用syslog。该日志文件意义非常重大,尤其是在架构rsync服务初期,可能会遇到相当多的问题,需要通过查看日志来定位问题所在。同时,即使为模块设置了log file,还是建议给全局设置一份,因为有些权限校验的异常,还是会被记录到全局日志文件里的。
    • read only:值取truefalse,决定客户端是否能往服务器端上传/删除文件,默认为false
    • write only:值取truefalse,决定客户端是否能从服务器端下载文件。
    • list:值取truefalse,决定客户端查询服务器端所有可用模块时是否显示,默认显示。
    • uid/gid:决定传输文件时以哪个身份(用户/组)进行传输,这关系到rsyncd是否有相应的文件系统权限来读取或修改文件。如果不设置此参数,则据此逻辑处理:如果rsyncd由超级用户启动,则以nobody这个系统用户的身份进行传输;否则,按启动rsyncd的用户身份进行传输。因此,如果想以root/root身份进行传输,则必须设置此参数为uid=root;gid=root
    • filter/include from/include/exclude from/exclude:表示同步文件的白名单及黑名单;虽然在rsync客户端使用的rsync命令里也有对应的可选参数,但在服务器端设置的话,更具有强制性和隐蔽性(在客户端访问的时候,只会反馈”不存在”,而非”不允许访问”)。
    • auth users:表示身份验证的规则,不设置则表示所有rsync用户都可访问。指定对象的方式有两种:1. 指定用户名,此用户名并不一定要真实存在于Linux系统中;2. 指定用户组名(并在用户组名前加上@以区分开用户名),这个方式是依托于Linux系统的,因此客户端连接使用的用户名以及此处指定的用户组都必须是真实存在于Linux系统中。多个对象可用空格或逗号进行分隔(推荐使用逗号,因为如果使用空格来分隔,那么在用户名/组名中带有空格的情况下,会造成混淆)。另外可以使用参数deny/ro(read only)/rw(read write)来具体控制某个用户或某个组的访问权限,如:auth users = , joe:deny, @Some Group:deny, admin:rw, @RO Group:ro
    • secrets file:指定一个声明用户名:用户密码@用户组名:用户组公共密码的文件,该参数是auth users参数的配套,仅在已设置auth users参数的情况下生效,且没有默认值。另外,即使你在auth users参数中指定了用户组作为对象,也不一定要在本文件中声明@用户组名:用户组公共密码,完全可以罗列出用户组中所有用户的用户名:用户密码来满足需求。
    • strict modes:值取truefalse,且默认值为true。如取true值,则secrits file参数所对应的文件,其文件系统权限必须设定为600。
    • hosts allow / hosts deny:表示rsync客户端的白名单及黑名单,可根据IP或IP段进行设置,且支持以空格为分隔符输入多个对象。

这里给出一份参考的rsyncd配置文件:

  1. port=873
  2. log file=/var/log/rsync.log
  3. pid file=/var/run/rsyncd.pid
  4. [test]
  5. path=/root/rsync/test
  6. use chroot=false
  7. max connections=0 # no limitation
  8. read only=false
  9. list=true
  10. uid=root
  11. gid=root
  12. auth users=rsyncuser
  13. secrets file=/etc/rsyncd.passwd
启动rsyncd

启动方式有以下两种:

  • 独立的服务:rsync --daemon --config=/etc/rsyncd.conf
  • inetd在监听到请求时再行启动,这里不作阐述。
rsyncd自启

为保证rsyncd的可用性(比如在系统异常重启后依然可用),需要把rsyncd设置为开机自启,具体方法请查询chkconfigsystemd

客户端
命令格式

在这种方式下的命令格式稍有区别:rsync [OPTION]... RSYNCUSER@HOST::[MODULE[/SRC]] DEST。多个对象的命令也有所区别:rsync [OPTION]... RSYNCUSER@HOST::[MODULE1[/SRC1]] ::[MODULE2[/SRC2]] ::[MODULE3[/SRC3]] DEST

关于用户身份验证

若rsyncd设置了auth users,那么客户端在连接的时候就需要提供相应rsync用户的密码了:

  • 直接用rsync [OPTION]... RSYNCUSER@HOST::[MODULE[/SRC]] DEST命令,接下来会提示需要输入密码。
  • 指定存放rsync用户密码的文件路径:`rsync -avL —password-file=/etc/rsyncd.passwd RSYNCUSER@HOST::[MODULE[/SRC]],此密码文件中,就只放密码:
    1. # cat /etc/rsyncd.passwd
    2. test123

rsync进阶运用

rsync配合inotify实现文件目录实时同步

需求假设是这样的:

  • 服务器A随着程序的执行,不断产生新的日志。
  • 服务器B和C需要把服务器A上的日志拉取过来,并需要保证实时性。

如果我们用crond轮询来启动rsync发起同步,不仅实时性得不到保证,另外也很可能造成资源的浪费。

那么,就有了下面这套方案:

  • 在服务器B和C上启动rsyncd。
  • 在服务器A上利用inotify监控日志的产生,每逢有新日志产生inotify都会调用我们写好的shell脚本,这样我们就可以在脚本中,把服务器A作为rsync客户端,远程连接服务器B和C,达到把服务器A上新产生的日志推送到服务器B和C上的目的。