Linux下rsync+inotify实现实时数据同步

一、 rsync


1. 什么是rsync


rsync 是一个远程数据同步工具, 可以实现本主机内,或跨主机的数据同步。以服务运行时监听在TCP 873端口, rsync演算法可以达到只传送文件变化的部分,而不是整个都传送,因此速度相当的快,性能不错。

所以rsync通常可以作为备份工具来使用。



1.1 rsync基本特点:


1. 可以镜像保存整个目录树或文件系统

2. 可以很容易做到保持原来文件的权限、时间、软硬链接等; (通过rsync的一些参数, 如 -a)

3. 较高的数据传输效率

4. 可以借助于rcp, ssh实现安全数据传输, 当然也可以通过直接的socket连接

5. 支持匿名传输



1.2 rsync命令语法:


rsync的命令格式可以分为以下几种:

rsync [OPTION]… SRC DEST
rsync [OPTION]… SRC [USER@]HOST:DEST
rsync [OPTION]… [USER@]HOST:SRC DEST
rsync [OPTION]… [USER@]HOST::SRC DEST
rsync [OPTION]… SRC [USER@]HOST::DEST
rsync [OPTION]… rsync://[USER@]HOST[:PORT]/SRC [DEST]


通过上面几种命令格式,可以总结rsync有以下4种不同的工作模式


1.3 rsync工作模式:


第一种模式: shell模式, 也称作本地模式:

通过shell使用unix socket进行连接。当源路径或目的路径的主机名后面包含一个冒号分隔符时使用这种模式,rsync安装完后就可以直接使用了,无所谓启动。


第二种模式: 远程shell模式, 可以利用ssh协议承载其远程传输过程

通过远程shell程序(ssh) 进行连接, 可以通过rsync参数 -e ssh来制定,和本地模式类似。


第三种模式: 列表模式, 仅列出源中的内容, -nv

只是列出同步内容,并不真正执行复制操作


第四种模式: 服务模式, 此时rsync工作为守护进程,能接受客户端的数据同步请求

也是比较常用的一种模式,当源路径或目的路径的主机名后面包含两个冒号,或使用rsync://URL时使用这种模式,无需远程shell,但必须在一台机器上启动rsync daemon,默认端口873,这里可以通过rsync --daemon使用独立进程的方式,或者通过xinetd超级进程来管理rsync后台进程。


当rsync作为daemon运行时,它需要一个用户身份。如果你希望启用chroot,则必须以root的身份来运行daemon,监听端口,或设定文件属主;如果不启用chroot,也可以不使用root用户来运行daemon,但该用户必须对相应的模块拥有读写数据、日志和lock file的权限。当rsync以daemon模式运行时,它还需要一个配置文件――rsyncd.conf。修改这个配置后不必重启rsync daemon,因为每一次的client连接都会去重新读取该文件。


我们一般把DEST远程服务器端称为rsync Server,运行rsync命令的一端SRC称为Client。



1.4 rsync命令的选项:

-n: 同步测试, 不执行真正的同步过程

-v: 详细输出模式

-q: 静默模式, 不输出信息

-c: checksum,开启校验功能

-r: 递归复制


注意: rsync命令中,如果源路径是目录,且给出复制路径末尾含有/, 则会复制目录中的内容,而非目录本身,如果路径末尾没有/,则会同步目录本身及目录中的所有文件。


目标路径末尾是否有/无关紧要


eg: 

# rsync /etc/yum.repo.d /tmp/test  此时源路径结尾不含/

则复制的是 yum.repo.d的文件夹本身及其内的所有文件

此时同步过去的目录结构为: /tmp/test/yum.repo.d



# rsync /etc/yum.repo.d/ /tmp/test 此时源路径结尾含有/

则复制的是/etc/yum.repo.d下所有的文件到/tmp/test/下


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

-p: 保留文件权限(rwx)

-t: 保留文件时间戳

-l: 保留符号链接

-g: 保留属组

-o: 保留属主


所以 -a相当用与 -rptlgo


-D: 保留设备文件


-e ssh: 使用ssh作为传输承载


-z: 压缩后传输


--progress: 显示进度条

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


2.同步测试:


了解了rsync的工作原理和命令解释,就可以用rsync来做同步测试了。


2.1 本机文件夹同步:

# rsync -a --progress /etc/fstab /tmp/back


会看到/etc/fstab文件传输到/tmp/back的列表和速率,再运行一次会看到 sending incremental file list



上面需要考虑以下问题:


删除/etc/fstab文件不会同步删除/tmp/back/fstab,除非加入--delete选项

文件访问时间等属性、读写等权限、文件内容等有任何变动,都会被认为修改

目标目录下如果文件比源目录还新,则不会同步

源路径的最后是否有斜杠有不同的含义:有斜杠,只是复制目录中的文件;没有斜杠的话,不但要复制目录中的文件,还要复制目录本身



2.2 远程服务器同步


在服务器间rsync传输文件,需要有一个是开着rsync的服务,而这一服务需要两个配置文件,说明当前运行的用户名和用户组,这个用户名和用户组在改变文件权限和相关内容的时候有用,否则有时候会出现提示权限问题。配置文件也说明了模块、模块化管理服务的安全性,每个模块的名称都是自己定义的,可以添加用户名密码验证,也可以验证IP,设置目录是否可写等,不同模块用于同步不同需求的目录。



2.2.1 设定rsync服务器端

# yum -y install xinetd

# chkconfig rsync on


2.2.2 为rsync提供配置文件

/etc/rsyncd.conf

    此配置文件分两段:

全局配置段: 1个

共享配置段: 多个,可自定义,是以[SHARED_NAME] 定义的



2.2.3 配置示例:  


# Global Settings
uid = nobody
gid = nobody
use chroot
max connections = 10
strict modes = yes 严格模式
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log
# Directory to be synced
[tools]
path = /data
ignore errors = yes 是否允许忽略错误
read only = no 
write only = no
host allow = 172.16.0.0/16 白名单列表
host deny = * 
list = true 是否允许列出文件?
uid = root  这个共享是以root用户运行的, 这里的共享配置可以覆盖global的里面的配置
gid = root
auth users=jingming
secrets file=/etc/rsyncd.secrets


这里配置以socket方式传输文件,[tools]自定义的一个共享目录配置,指定了要同步的目录path, 授权用户,密码文件, 允许哪天服务器IP同步发送等, 配置文件中各个参数具体定义可以通过

 # man rsyncd.conf

查看手册


密码文件/etc/rsynced.secrets内格式为:

username:password 

内容为明文,一行一个用户,密码。 这里的密码和系统用户无关,是自定义设置的

这里定义的用户要和/etc/rsyncd.conf的auth users 对应


修改权限: 

# chmod 600 /etc/rsyncd.secrets

 

确保除了root,任何人不能访问此文件




2.2.4 启动rsync后台服务

修改/etc/xinetd.d/rsync文件, disable改为no

# service xinetd restart


也可以使用

# /usr/bin/rsync --daemon --config=/etc/rsyncd.conf


为了防止rsync写入过多的无用日志到/var/log/message (容易塞满从而错过重要的信息) 建议注释掉/etc/xinetd.conf的success

# log_on_success = PID HOST DURATION EXIT


如果使用的防火墙,要添加放行tcp 873端口的规则


# iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 87 -j ACCEPT
# iptables -L
# netstat -tnl | grep 873



建议关闭selinux, 可能会由于强访问控制导致同步报错。


2.3 客户端测试同步

# 将本地/root/目录同步到远程192.168.181.100上的/data目录(共享配置中[tools]段指定的)
# rsync -ar --progress /root/ [email protected]::tools


#将远程的/data目录同步到本地的/tmp/back
# rsync -ar --progress [email protected]:tools /tmp/back


也可以给客户端指定一个密码文件,就可以无需交互,直接复制:

# rsync -arP --progress --password-file=/etc/rsync_client.pwd [email protected]::tools /tmp

密码文件只记录密码,记得将权限设置600

# echo "passowd_for_jingming" > /etc/rsync_client
# chmod 600 /etc/rsync_client



从上面两个命令可以看到,其实这里的服务器与客户端的概念是很模糊的,rsync daemon都运行在远程192.168.18.100上,第一条命令是本地主动推送目录到远程,远程服务器是用来备份的;第二条命令是本地主动向远程索取文件,本地服务器用来备份,也可以认为是本地服务器恢复的一个过程。



2.4 rsync的局限性:


与传统的cp、tar备份方式相比,rsync具有安全性高、备份迅速、支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期的备份文件服务器数据到远端服务器,对本地磁盘定期做数据镜像等。


随着应用系统规模的不断扩大,对数据的安全性和可靠性也提出的更好的要求,rsync在高端业务系统中也逐渐暴露出了很多不足,首先,rsync同步数据时,需要扫描所有文件后进行比对,进行差量传输。如果文件数量达到了百万甚至千万量级,扫描所有文件将是非常耗时的。而且正在发生变化的往往是其中很少的一部分,这是非常低效的方式。其次,rsync不能实时的去监测、同步数据,虽然它可以通过crontab方式进行触发同步,但是两次触发动作一定会有时间差,这样就导致了服务端和客户端数据可能出现不一致,无法在应用故障时完全的恢复数据。基于以上原因,rsync+inotify组合出现了!




二、 inotify-tools


2.1 什么是inotity


inotiy是一种强大的、细粒度的、异步的文件系统事件监控机制,Linux内核从2.6.13开始引入, 允许监控程序打开一个独立文件描述符,并针对事件集监控一个或者多个文件,例如打开、关闭、移动、重命名、删除、创建或者改变属性。


CentOS6已经原声支持:

使用 # ll /proc/sys/fs/inotify 命令, 是否有以下三条信息输出,如果没有表示不支持:


# ll /proc/sys/fs/inotify/
total 0
-rw-r--r-- 1 root root 0 Aug 21 19:35 max_queued_events
-rw-r--r-- 1 root root 0 Aug 21 19:35 max_user_instances
-rw-r--r-- 1 root root 0 Aug 21 19:35 max_user_watches



/proc/sys/fs/inotify/max_queued_evnets表示调用inotify_init时分配给inotify instance中可排队的event的数目的最大值,超出这个值的事件被丢弃,但会触发IN_Q_OVERFLOW事件。

/proc/sys/fs/inotify/max_user_instances表示每一个real user ID可创建的inotify instatnces的数量上限。

/proc/sys/fs/inotify/max_user_watches表示每个inotify instatnces可监控的最大目录数量。如果监控的文件数目巨大,需要根据情况,适当增加此值的大小。




2.2 什么是inotify-tools:


inotify-tools是为linux下inotify文件监控工具提供的一套C的开发接口库函数,同时还提供了一系列的命令行工具,这些工具可以用来监控文件系统的事件。 inotify-tools是用c编写的,除了要求内核支持inotify外,不依赖于其他。inotify-tools提供两种工具,一是inotifywait,它是用来监控文件或目录的变化,二是inotifywatch,它是用来统计文件系统访问的次数



2.2.1 inotify-tools编译安装

# tar xf inotify-tools-3.13.tar.gz
# cd inotify-tools-3.13
# ./configure
# make && make install



默认会释放inotifywait和inotifywatch命令到/usr/local/bin下





2.3 inotifywait使用实例:


监控/root/tmp目录文件的变化:

# /usr/local/bin/inotifywait -mrq --timefmt '%Y/%m/%d-%H:%M:%S' --format '%T %w %f' \
# -e modify,delete,create,move,attrib /root/tmp/



上面的命令表示,持续监听/root/tmp目录及其子目录的文件变化,监听事件包括文件被修改、删除、创建、移动、属性更改,显示到屏幕。执行完上面的命令后,在/root/tmp下创建或修改文件都会有信息输出:


[root@www ~]# inotifywait -mrq --timefmt '%Y/%m/%d-%H:%M:%S' --format '%T %w %f' \
> -e modify,delete,create,move,attrib /tmp/backup
2015/08/21-19:42:29 /tmp/backup/ 1.txt
2015/08/21-19:42:39 /tmp/backup/ 2.txt
2015/08/21-19:42:39 /tmp/backup/ 2.txt
2015/08/21-19:42:47 /tmp/backup/ .3.txt.swp
2015/08/21-19:42:47 /tmp/backup/ .3.txt.swx
2015/08/21-19:42:47 /tmp/backup/ .3.txt.swx
2015/08/21-19:42:47 /tmp/backup/ .3.txt.swp
2015/08/21-19:42:47 /tmp/backup/ .3.txt.swp
2015/08/21-19:42:47 /tmp/backup/ .3.txt.swp
2015/08/21-19:42:51 /tmp/backup/ .3.txt.swp
2015/08/21-19:42:54 /tmp/backup/ .3.txt.swp



三、 rsync组合inotify-tools完成实时同步


这一步的核心气势就是在客户端创建一个脚本rsync.sh, 适用inotifywait监控本地目录的变化, 触发rsync将变化的文件传输到远程备份服务器上。

为了更接近实战, 我们要求一部分子目录不同步, 如/tmp/backup/log和临时文件



3.1 创建排除在外不同步的文件列表


排除不需要同步的文件或目录有两种做法,

第一种是inotify监控整个目录,在rsync中加入排除选项,简单;

第二种是inotify排除部分不监控的目录,同时rsync中也要加入排除选项,可以减少不必要的网络带宽和CPU消耗。我们选择第二种。



3.1.1 inotifywait排除


这个操作在客户端进行,假设/tmp/src/mail/2014/以及/tmp/src/mail/2015/cache/目录下的所有文件不用同步,所以不需要监控,/tmp/src/下的其他文件和目录都同步。(其实对于打开的临时文件,可以不监听modify时间而改成监听close_write)


inotifywait排除监控目录有--exclude <pattern>和--fromfile <file>两种格式,并且可以同时使用,但主要前者可以用正则,而后者只能是具体的目录或文件。


# vim /etc/inotify_exclude.lst:
/tmp/src/pfd
@/tmp/src/2014


如果要排除的格式比较复杂,必须使用正则,那只能在inotifywait中加入选项

如--exclude '(.*/*\.log|.*/*\.swp)$|^/tmp/src/mail/(2014|201.*/cache.*)'

表示排除/tmp/src/mail/以下的2014目录,和所有201*目录下的带cache的文件或目录,以及/tmp/src目录下所有的以.log或.swp结尾的文件。



3.1.2 rsync排除


使用inotifywait排除监控目录的情况下,必须同时使用rsync排除对应的目录,否则只要有触发同步操作,必然会导致不该同步的目录也会同步。与inotifywait类似,rsync的同步也有--exclude和--exclude-from两种写法。


个人还是习惯将要排除同步的目录写在单独的文件列表里,便于管理。

使用--include-from=FILE时,排除文件列表用绝对路径,但FILE里面的内容请用相对路径,如:

/etc/rsyncd.d/rsync_exclude.lst:
mail/2014/
mail/201*/201*/201*/.??*
mail??*
src/*.html*
src/js/
src/ext3/
src/2014/20140[1-9]/
src/201*/201*/201*/.??*
membermail/
membermail??*
membermail/201*/201*/201*/.??*


排除同步的内容包括,mail下的2014目录,类似2015/201501/20150101/下的临时或隐藏文件,等。



3.2 客户端同步到远程的脚本:


下面是一个完成的同步脚本, 请根据需要进行裁剪,rsync.sh

#rsync auto sync script with inotify
#2015-08-21 Richie Jing
#variables
current_date=$(date +%Y%m%d_%H%M%S)
source_path=/tmp/src/
log_file=/var/log/rsync_client.log
#rsync
rsync_server=192.168.18.100
rsync_user=jingming
rsync_pwd=/etc/rsync_client.pwd
rsync_module=tools
INOTIFY_EXCLUDE='(.*/*\.log|.*/*\.swp)$|^/tmp/src/mail/(2014|20.*/.*che.*)'
RSYNC_EXCLUDE='/etc/rsyncd.d/rsync_exclude.lst'
#rsync client pwd check
if [ ! -e ${rsync_pwd} ];then
    echo -e "rsync client passwod file ${rsync_pwd} does not exist!"
    exit 0
fi
#inotify_function
inotify_fun(){
    /usr/bin/inotifywait -mrq --timefmt '%Y/%m/%d-%H:%M:%S' --format '%T %w %f' \
          --exclude ${INOTIFY_EXCLUDE}  -e modify,delete,create,move,attrib ${source_path} \
          | while read file
      do
          /usr/bin/rsync -auvrtzopgP --exclude-from=${RSYNC_EXCLUDE} --progress --bwlimit=200 --password-file=${rsync_pwd} ${source_path} ${rsync_user}@${rsync_server}::${rsync_module} 
      done
}
#inotify log
inotify_fun >> ${log_file} 2>&1 &



--bwlimit=200用于限制传输速率最大200kb,因为在实际应用中发现如果不做速率限制,会导致巨大的CPU消耗。


在客户端运行脚本

# ./rsync.sh

即可实时同步目录。



博客参考了:

http://segmentfault.com/a/1190000002427568

感谢原博主的分享

你可能感兴趣的:(rsync,inotify-tools)