一、rsync概述

1、rsync简介

  rsync:remote sync  远程同步

  rsync是Linux/unix系统下的文件同步和数据传输工具,它采用的“rsync”算法,使一个客户机和远程文件服务器之间的文件同步。通过rsync可以将同一个服务器的数据从一个分区备份到另一个分区,也可以将本地系统的数据通过网络传输当时备份到任何一个远程主机上,rsync可以在中断之后恢复传输,rsync只传输源文件和目标文件之间不一致的部分,rsync可以执行完整备份或增量备份。

  rsync能够实现cp命令的功能:将文件从一个位置复制到另一个位置

  也能够实现scp命令的共能:将文件从一个主机复制到另个主机(rsync本身不具备加密功能)   

2、rsync的工作机制       

  rsync比起cp和scp复制文件有一个显而易见的好处:快速

  rsync同步文件时,先比较两个文件的特征码是否一致,如果一致则源和目标一样,则不需同步,不一致则使用源文件覆盖目标文件。 

 

3、rsync的功能特性

 1)可以镜像保存整个目录树和文件系统;

 2)可以增量同步数据,文件传输效果高,因而同步时间很短;

 3)可以保持原有文件的权限,时间等属性;

 4)加密传输数据,可以保证数据的安全性;

 5)可以使用rcp ssh等方式传输文件,当然也可以通过Socket连接传输文件;

 6)支持匿名传输。


4、rsync的优点和不足

  rsync具有安全性高,备份迅速,支持增量备份的优点,通过rsync可以解决对实时性要求不高的数据备份需要。

rsync在高端业务系统中逐渐暴露出很多的不足:

  rsync同步数据时,需要扫描所有文件后进行对比,然后进行差量传输。如果如文件数量达到百万甚至千万量级,扫描所有文件将是非常耗时的。

  其次rsync不能实时监控同步数据。


二、rsync的使用

1、rsync常用命令选项

 -n,--dry-run:试运行,

             在不确定命令是否能按意愿执行时,务必要事先测试,-n可以完成此功能;

 -v,--verbose:详细输出模式;

[root@Node1 tmp]# rsync etc/passwd test -n
[root@Node1 tmp]# rsync etc/passwd test -nv
passwd

sent 30 bytes  received 15 bytes  90.00 bytes/sec
total size is 1408  speedup is 31.29 (DRY RUN)
[root@Node1 tmp]# ls test
[root@Node1 tmp]# rsync etc/passwd test 
[root@Node1 tmp]# ls test
passwd
[root@Node1 tmp]# rsync etc/passwd test -v
passwd

sent 1478 bytes  received 31 bytes  3018.00 bytes/sec
total size is 1408  speedup is 0.93

 -q,--quiet:静默模式,

 -c,--checksum:开启校验功能,强制对文件传输进行校验;

 -r,--recursive:递归复制;

注意:

  rsync命令使用时,如果源参数的末尾有斜线,就会复制指定目录的内容,而不会复制目录本身;如果没有斜线,则会复制目录本身;目标参数末尾的斜线没有作用

  命令使用如下:

     # rsync -r /mydata/data /backups/   :会把目录data直接同步到/backups目录中

     # rsync -r /mydata/data/ /backups/   :会把目录data/中的所有文件直接同步到/backups目录中;


 -a,--archives:归档,保留文件的原有属性;

   -p,--perms:保留文件的权限;

   -t,--times:保留文件的时间戳;

   -l,--links:保留文件的符号链接;

   -g,--group:保留文件的属组;

   -o,--owne:保留文件的属主;

   -D,--devices:保留设备文件

 -e ssh:表示使用ssh协议作为承载;

      如果sshd的端口不是默认的,则使用 -e "ssh -p 端口号"

 -z:基于网络时使用,对文件压缩后传输;

 -p,--progress: 显示进度条;

 --stats:显示如何执行压缩和传输的过程


2、rsync的工作模式

   rsync有四种工作模式

1)shell模式

   类似cp,也称为本地模式

语法格式:

  rsync [OPTION]... SRC [SRC]... DEST

[root@Node1 tmp]# ls /root/src
Discuz_X3.3_SC_UTF8.zip  php-7.1.1  php-7.1.1.bak  php-7.1.1.tar.gz  phpa.zip  test
[root@Node1 tmp]# rsync -a /tmp/etc /root/src
[root@Node1 tmp]# ls /root/src
Discuz_X3.3_SC_UTF8.zip  etc  php-7.1.1  php-7.1.1.bak  php-7.1.1.tar.gz  phpa.zip  test
[root@Node1 tmp]# rsync -a /tmp/etc /tmp/vmware-root /root/src
[root@Node1 tmp]# ls /root/src
Discuz_X3.3_SC_UTF8.zip  php-7.1.1      php-7.1.1.tar.gz  test
etc                      php-7.1.1.bak  phpa.zip          vmware-root
[root@Node1 tmp]# rsync -a /tmp/vmware-root/ /root/src
[root@Node1 tmp]# ls /root/src
Discuz_X3.3_SC_UTF8.zip  vmware-apploader-1001.log  vmware-apploader-1139.log
etc                      vmware-apploader-1004.log  vmware-apploader-18689.log
php-7.1.1                vmware-apploader-1006.log  vmware-apploader-18697.log
php-7.1.1.bak            vmware-apploader-1018.log  vmware-apploader-18735.log
php-7.1.1.tar.gz         vmware-apploader-1020.log  vmware-apploader-18795.log
phpa.zip                 vmware-apploader-1069.log  vmware-apploader-988.log
test                     vmware-apploader-1087.log  vmware-apploader-993.log
vmware-18735.log         vmware-apploader-1117.log  vmware-root
vmware-18795.log         vmware-apploader-1124.log

2)远程shell模式

   类似scp,此时可以利用ssh协议承载其数据传输过程

语法格式:

 Pull:拉取文件,获取目标文件

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

 Push:推送,上传文件 

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

[root@Node1 tmp]# rsync -a -e ssh /tmp/etc 192.168.10.4:/root/src
root@192.168.10.4's password:

   需要注意,远端主机上一定要安装rsync,不然会执行失败(rsync命令找不到)


3)列表模式   

   其工作方式与ls -l相似,仅列出源的内容

语法格式:

  rsync [OPTION]... SRC

[root@Node1 tmp]# rsync test
drwxr-xr-x        4096 2017/02/10 11:33:14 test
[root@Node1 tmp]# ls  test
vmware-root
[root@Node1 tmp]# rsync test/
drwxr-xr-x        4096 2017/02/10 11:33:14 .
drwx------        4096 2017/02/10 11:33:14 vmware-root
[root@Node1 tmp]# ls  test/
vmware-root
[root@Node1 tmp]# ls -l test
total 4
drwx------ 2 root root 4096 Feb 10 11:33 vmware-root

[root@Node1 tmp]# rsync 192.168.10.4:/root
root@192.168.10.4's password: 
dr-xr-x---        4096 2017/02/10 09:04:10 root

  通过上面的输出,可以看出来,rsync后跟文件或目录和ls -l后跟文件和目录的效果大体相同。需要注意的是,如果你身处某个目录,你"ls -l"能查看到所在目录下文件列表的详细信息。但是你执行rsync会报错,因此rsync必须后跟文件或目录才能查看相关的详细信息。

  另外,rsync的列表模式是支持对远端的目录进行查看的,而ls -l是不具备这个功能的。


4)服务器模式

   此时rsync可以工作为守护进程,能够接收客户端的数据传输请求;在使用时,可以在客户端使用rsync命令把文件发送给守护进程,也可以向服务器获取数据文件。


三、配置rsync服务器模式

1、设定rsync服务器端

安装xinetd并启动xinetd:

[root@Node1 tmp]# yum install xinetd
[root@Node1 tmp]# service xinetd start
[root@Node1 tmp]# chkconfig rsync on

[root@Node1 tmp]# ss -tunap|grep xinetd
tcp    LISTEN     0      64                    :::873                  :::*      users:(("xinetd",49313,5))

  rsync服务端可同时备份多个客户端的数据,和多个服务端备份一个客户端的数据。rsync默认端口为tcp 873,服务器在该端口接收客户的匿名或者认证方式的备份请求。


2、为rsync服务提供配置文件  

  rsync服务端在使用之前需要进行必要的配置,其配置文件为/etc/rsyncd.conf,该文件默认没有,需要自己手动创建。Rsync服务端通过/etc/rsyncd.conf进行认证、访问、日志记录等控制,

该配置文件定义一个全局配置和多各rsync共享配置。


常用的配置:

# Global Settings

uid = rsync      # 指定以哪个用户同步数据     

gid = rsync      # 指定以哪个用户组同步数据

port = 873        # 指定监听端口

use chroot = no   # 默认为true,修改为no,否则配置麻烦

max connections = 200  

                # 指定最大并发连接数以保护服务器,超过限制的连接请求将被告知随后再试。默认值为0,即没有限制。

strict modes = yes    # 严格检查文件权限等相关信息

timeout = 300               # 服务器会话的超时时间

pid file = /var/run/rsyncd.pid    # 进程启动后,进程号存放路径

lock file = /var/run/rsyncd.lock  # 服务启动、停止会用到锁文件

log file = /var/log/rsyncd.log    # 指定日志文件的路径

Log fromat = %h %o %f %l %b   # 指定日志记录的格式

#motd file = /etc/rsyncd.motd     # 登陆消息提示文件,可以不配置。默认为空。


# Director to be synced    以下是用于接受用户同步数据的目录的配置

[synced_name]     # 待同步文件的名称,和nfs导出的共享文件名一样

# Comment = "string"  # 描述信息,该描述连同模块名在客户连接得到模块列表时显示给客户。默认没有描述定义

path = /path/to/some_dir   # 指定供同步数据的目录路径,必须指定该参数。该目录路径是rsync服务端的一个路径,提供给客户端上传或下载

ignore erros = yes   # 忽略错误,同步文件时,如果有一个文件报错,是继续同步还是终止呢?

read only = no    # 只读,用户是否只能拉取数据,不能上传数据

write only = no     # 只写,用户是否只能上传数据,不能拉取数据,

hosts allow = 192.168.137.0/24  # 白名单:指定允许客户连接的IP地址。可以为单个IP地址或整个网段或主机名。多个IP或网段需要以空格隔开。默认是允许所有主机连接。

hosts deny = *    # 指定拒绝连接的客户IP地址,设置方式和hosts allow相同。


注意:

         1.默认规则为允许访问,二者都不出现时

         2.只出现hosts allow:定义白名单;但没有被匹配到的由默认规则处理,即为允许

         3,只出现hosts deny:定义黑名单;出现在名单中的都被拒绝

         4.二者同时出现,先检查hosts allow,如果匹配就allow,否则,检查hosts deny 如果匹配则拒绝,如二者均无匹配,则使用默认的,即允许


list = false     # 是否允许用户列出文件,默认值为true

uid = root  # 以哪个用户获取文件

gid = root  # 以哪个用户组获取文件 

auth users = rsync_backup  # 该选项指定由空格或逗号分隔的用户名列表,只有这些用户才允许连接该模块。这里的用户不一定是客户端存在的用户。如果"auth users"被设置,那么客户端发出对该模块的连接请求时,需要对用户身份进行验证。用户的名和密码以明文方式存放在"secrets file"选项指定的文件中。默认情况下无需密码就可以连接模块 (也就是匿名方式)。

secrets file = /etc/rsync.password # 虚拟用户的密码文件


   rsyncd.conf文件中[module]之前的所有参数为全局参数,也可以在全局参数部分定义模块参数。在这种情况下该参数的值就是所有模块的默认值。全局参数设置程序使用的端口号,指定消息文件、日志文件pid文件以及发送日志消息的级别。模块参数主要定义服务端哪个目录需要被同步。用户可根据不同的需要指定多个模块,每个模块对应需要备份的一个目录树,即若有 N 个需要备份的目录树,则需要 N 个模块与之对应。模块中可以定义许多参数。

[root@Node1 ~]# cat /etc/rsyncd.conf
# Global  Settings
uid = nobody
gid = nobody
use chroot = no
max connetions = 5
strict modes = yes
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log
  
# Directory to be rsynced 
[mydata]
path = /data/mydata
ignore errors = yes
read only = no
write only = no
hosts allow = 192.168.10.0/24
hosts deny = * # 通过所有主机
list = false
uid = root
gid = root
auth users = myuser
secrets file = /etc/rsyncd.passwd
[root@Node1 ~]#

3、为rsync提供密码文件

文件格式(明文):

  username:password

  文件权限要设置为600,一定要设置,不设置的同步不成功

[root@Node1 ~]# vim /etc/rsyncd.passwd 

[root@Node1 ~]# cat /etc/rsyncd.passwd
myuser:mypasswd
[root@Node1 ~]# chmod 600 /etc/rsyncd.passwd


4、配置服务能够启动

service xinetd start

chkconfig rsync on

[root@Node1 ~]# service xinetd restart
Stopping xinetd:                                           [  OK  ]
Starting xinetd:                                           [  OK  ]
[root@Node1 ~]# ss -tunap|grep xinet
tcp    LISTEN     0      64                    :::873                  :::*      users:(("xinetd",49544,5))

  也可以直接手动启动rsync为后台守护进程,而不经过xinetd托管:

[root@Node1 mydata]# service xinetd stop    
Stopping xinetd:                                           [  OK  ]
[root@Node1 mydata]# ss -tunap|grep 873
[root@Node1 mydata]# rsync --daemon     
                                      # 注意如果你的rsyncd.conf文件在/etc/目录下,就不需要再用--config去指定了。--daemon是以守护进程的方式启动
[root@Node1 mydata]# ss -tunap|grep 873
tcp    LISTEN     0      5                     :::873                  :::*      users:(("rsync",49772,5))
tcp    LISTEN     0      5                      *:873                   *:*      users:(("rsync",49772,3))


5、在客户端配置并测试

Access via 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

[root@Node5 ~]# rsync 105.txt myuser@192.168.10.1::mydata
Password: 

[root@Node1 mydata]# ls
105.txt  test_file

[root@Node5 ~]# rsync myuser@192.168.10.1::mydata/test_file .
Password: 

[root@Node5 ~]# ls test_file 
test_file

  这里客户端还需要交互式的输入用户的密码,那如何避免输入密码呢?

    1)在rsync服务器配置文件中不定义auth users和secrets file两个选项,以匿名用户的方式登录 

    2)在客户端本地也创建一个本地密码文件,该密码文件只要保存了rsync服务端用户帐户的密码就可以了(不需要保存帐户)。

[root@Node5 ~]# vim /etc/rsync.passwd
[root@Node5 ~]# cat /etc/rsync.passwd
mypasswd
[root@Node5 ~]# chmod 600 /etc/rsync.passwd    # 客户端这也需要修改权限


[root@Node5 ~]# rsync --password-file=/etc/rsync.passwd myuser@192.168.10.1::mydata/test_file .

注意:

  这里用的帐号和密码就和系统登录的帐号密码没有关系了,使用的是上面配置好的帐号和密码

  如果需要做周期性操作,则需要将命令写入cronttab中


常用的两个选项:

  --delete:删除目标目录中多余的文件

           就是完全和源文件一样,删除目标目录(需要同步的目录)中多余的文件

# 测试环境
[root@rsync-server ~]# ls /test/    # 查看rsync服务端共享目录下的文件
e
[root@rsync-client ~]# ls /test/    # 查看rsync客户端本地/test目录的文件列表
a  b  c  d

# 拉取,
[root@rsync-client ~]# rsync -avzP --delete rsync_backup@172.16.100.1::sunsky  /test --password-file=/etc/rsync.password
receiving incremental file list
deleting d
deleting c
deleting b
deleting a
./
e
           0 100%    0.00kB/s    0:00:00 (xfer#1, to-check=0/2)
  
sent 86 bytes  received 143 bytes  458.00 bytes/sec
total size is 0  speedup is 0.00
[root@rsync-client ~]# ls /test/
e 
[root@rsync-server ~]# ls /test/
e

# 推送,需要先恢复测试环境
[root@rsync-client ~]# rsync -avzP --delete /test/ rsync_backup@172.16.100.1::sunsky --password-file=/etc/rsync.password
sending incremental file list
./
deleting e
a
           0 100%    0.00kB/s    0:00:00 (xfer#1, to-check=3/5)
b
           0 100%    0.00kB/s    0:00:00 (xfer#2, to-check=2/5)
c
           0 100%    0.00kB/s    0:00:00 (xfer#3, to-check=1/5)
d
           0 100%    0.00kB/s    0:00:00 (xfer#4, to-check=0/5)
  
sent 201 bytes  received 87 bytes  576.00 bytes/sec
total size is 0  speedup is 0.00
[root@rsync-client ~]# ls /test/
a  b  c  d
[root@rsync-server ~]# ls /test/
a  b  c  d

 --exclude=PATTERN:不同步被模式匹配的文件

 --exclude-from=FILE:不同步该配置文件中定义的文件    

# 测试环境
[root@rsync-server ~]# tree /test/
/test/
0 directories, 0 files
[root@rsync-client ~]# tree /test/
/test/
├── a
├── b
├── c.txt
├── x
│   └── xxx.txt
└── x.txt
2 directories, 4 files

# 推送
[root@rsync-client ~]# rsync -avz --exclude=*.txt /test/ root@172.16.100.1:/test/
root@172.16.100.1's password: 
sending incremental file list
./
a
b
x/
sent 154 bytes  received 57 bytes  60.29 bytes/sec
total size is 0  speedup is 0.00

[root@rsync-server ~]# tree /test/
/test/
├── a
├── b
└── x
1 directory, 2 files

# 推送,需先恢复测试环境
[root@rsync-client ~]# cat /tmp/exclude 
x
*.txt
[root@rsync-client ~]# rsync -avz --exclude-from=/tmp/exclude /test/ root@172.16.100.1:/test/
root@172.16.100.1's password: 
sending incremental file list
./
a
b
xx/
sent 151 bytes  received 57 bytes  59.43 bytes/sec
total size is 0  speedup is 0.00

[root@rsync-server ~]# tree /test/
/test/
├── a
├── b
└── xx
1 directory, 2 files

总结:

   在生产环境中,我们可以专门部署一台rsync服务器,专门负责接收业务服务器的日志归档和配置文件归档。当然,我们也可以部署在svn服务器之前,来作为网站代码推送的服务器,或者说一台web服务器专门用来做分发的时候。

  但是我们知道,我们的日志归档都是在凌晨,因此我们不可能天天晚上去做向rsync服务端的推送操作。并且,如果日常web内容做分发的次数频繁的话,我们不可能每时每刻都盯着它去做手动推送。因此我们可以借助crontab计划任务来实现定时推送。

 但是,我们仍然会发现一个问题,虽然使用周期性计划任务能满足我们的日志归档定时推送到rsync服务端,但是每次都有1分钟的延迟。并且,在某些作为网站发布平台的情况下,rsync每分钟都去检查整体一致性然后做推送,这样子非常耗费资源。因此,我们需要对此种情况进行改良。在后面一篇博文,学习了解rsync+inotify,借助rsync+inotify来实现实时同步文件。