0基础linux运维教程 Rsync结合inotify实现数据实时同步

不飞则已,一飞冲天;不鸣则已,一鸣惊人。这篇文章主要讲述0基础linux运维教程 Rsync结合inotify实现数据实时同步相关的知识,希望能为你提供帮助。
了解rsync的优缺点之后,就需要了解Rsync结合inotify实现数据如何实时同步,以下案例可以供童鞋们一起学习下
七 Rsync结合inotify实现数据实时同步7.1 rsync+inotify介绍
rsync+crond:只能实现数据的间隔同步(最小也是分钟级别的同步),无法实现实时同步,如果要做异地镜像点,肯定是需要实时同步的。 在Linux kernel 2.6.13后提供了inotify文件系统监控机制。通过rsync+inotify组合可以实现实时同步,制作异地镜像站点,以便为异地备份做好准备工作
7.2 安装inotify-tools
inotify由inotify-tools包提供。在安装inotify-tools之前,请确保内核版本高于2.6.13,且在/proc/sys/fs/inotify目录下有以下三项,这表示系统支持inotify监控,关于这3项的意义,下文会简单解释。

[root@local ~]# ll /proc/sys/fs/inotify/
total 0
-rw-r--r-- 1 root root 0 Feb 11 19:57 max_queued_events
-rw-r--r-- 1 root root 0 Feb 11 19:57 max_user_instances
-rw-r--r-- 1 root root 0 Feb 11 19:57 max_user_watches

epel源上提供了inotify-tools工具,或者下载源码包格式进行编译。 inotify-tools源码包地址: 以下为编译安装过程:
tar xf inotify-tools-3.14.tar.gz
./configure --prefix=/usr/local/inotify-tools-3.14
make & & make install
ln -s /usr/local/inotify-tools-3.14 /usr/local/inotify

inotify-tools工具只提供了两个命令。
[root@local ~]# rpm -ql inotify-tools | grep bin/
/usr/bin/inotifywait
/usr/bin/inotifywatch

其中inotifywait命令用于等待文件发生变化,所以可以可以实现监控(watch)的功能,该命令是inotify的核心命令。inotifywatch用于收集文件系统的统计数据,例如发生了多少次inotify事件,某文件被访问了多少次等等,一般用不上。 以下是inotify相关的内核参数。
(1)./proc/sys/fs/inotify/max_queued_events:调用inotify_init时分配到inotify instance中可排队的event数的最大值,超出值时的事件被丢弃,但会触发队列溢出Q_OVERFLOW事件。
【0基础linux运维教程 Rsync结合inotify实现数据实时同步】(2)./proc/sys/fs/inotify/max_user_instances:每一个real user可创建的inotify instances数量的上限。
(3)./proc/sys/fs/inotify/max_user_watches:每个inotify实例相关联的watches的上限,即每个inotify实例可监控的最大目录、文件数量。如果监控的文件数目巨大,需要根据情况适当增加此值。
如:
[root@xuexi ~]# echo 30000000 > /proc/sys/fs/inotify/max_user_watches

7.3 inotifywait命令与事件
7.3.1 inotifywait命令
选项
说明
-m
持续监听
-r
使用递归形式监视目录
-q
减少冗余信息,只打印出需要的信息
-e
指定要监视的事件,多个时间使用逗号隔开
–timefmt
时间格式
–format
监听到的文件变化的信息,信息格式自定义,详解下表
–format 参数说明:
参数
说明
%w
表示发生事件的目录
%f
表示发生事件的文件,%w%f组在一起即表发生事件的绝对路径
%e
表示发生的事件,事件默认是以逗号为分隔符的,例如CLOSE_WRITE,CLOSE
%Xe
事件以“X”分隔,例如CLOSE_WRITEXCLOSE,代表事件CLOSE_WRIT与CLOSE
%T
使用由--timefmt定义的时间格式,此时必须指定--timefmt参数
-e指定的监控事件
create:在被监控的目录中创建了文件或目录
delete:删除了被监控目录中的某文件或目录
modify:修改,文件内容被修改
access:文件被访问
attrib:元数据被修改。包括权限、时间戳、扩展属性等等
close_write:打开的文件被关闭,是为了写文件而打开文件、随后被关闭的事件,比如用vim编辑文件或者echo 1111 > > egon.txt
close_nowrite:read only模式下文件被关闭,即只能是为了读取而打开文件,读取结束后关闭文件的事件
close:是close_write和close_nowrite的结合,无论是何种方式打开文件,只要关闭都属于该事件
open:文件被打开
moved_to:向监控目录下移入了文件或目录,也可以是监控目录内部的移动
moved_from:将监控目录下文件或目录移动到其他地方,也可以是在监控目录内部的移动
move:是moved_to和moved_from的结合
moved_self:被监控的文件或目录发生了移动,移动结束后将不再监控此文件或目录
delete_self:被监控的文件或目录被删除,删除之后不再监控此文件或目录
umount:挂载在被监控目录上的文件系统被umount,umount后不再监控此目录
isdir :监控目录相关操作

7.3.2 事件分析监控目录
[root@egon < sub> ]# mkdir /egon_bak
[root@egon < /sub> ]# inotifywait -m /egon_bak/ #在前台监控目录/egon_bak,未指定监控的事件,默认监控所有
Setting up watches.
Watches established.

打开另外一个终端,对被监控目录/egon_bak进行一些操作,来查看触发的事件
验证文件的增删改查,vim编辑文件,cp拷贝,mv移动文件等操作触发的事件
验证目录的增删改查,cp拷贝文件到目录下,mv移入移出等操作触发的事件

大致总结如下
# 文件的增删改
监控目录下新增了某个文件-> 触发的事件:
CREATE
MODIFY
CLOSE_WRITE,CLOSE
监控目录下的某个文件被删除-> 触发的事件
DELETE
监控目录下的某个文件内容被修改-> 触发的事件
MODIFY
CLOSE_WRITE,CLOSE
监控目录下的某个文件属性被修改-> 触发的事件
ATTRIB
监控目录下的某个文件被mv到别的目录中-> 出发的事件
MOVED_FROM
某个文件被mv到了监控目录或其子目录下-> 出发的事件
MOVED_TO
# 目录的增删改同上
CREATEXISDIR
DELETEXISDIR
ATTRIBXISDIR
MOVED_FROMXISDIR
MOVED_TOXISDIR

从上面的测试结果中可以发现,很多动作都涉及了close事件,且大多数情况都是伴随着close_write事件的。所以,大多数情况下在定义监控事件时,其实并不真的需要监控open、modify、close事件。特别是close,只需监控它的分支事件close_write和close_nowrite即可。由于一般情况下inotify都是为了监控文件的增删改,不会监控它的访问,所以一般只需监控close_write即可。 由于很多时候定义触发事件后的操作都是根据文件来判断的,例如a文件被监控到了变化(不管是什么变化),就立即执行操作A,又由于对文件的一个操作行为往往会触发多个事件,例如cat查看文件就触发了open、access、close_nowrite和close事件,这样很可能会因为多个事件被触发而重复执行操作A。 综合以上考虑,我们应该尽量做到监控对象减少重复,但这一点其实很难实现
inotifywait -mrq --timefmt \'%Y-%m-%d %H:%M:%S\' --format \'%w%f:%Xe:%T\' -e create,delete,modify,move,attrib,close_write /test

7.3.3 rsync+inotify脚本
该脚本需要运行在本地 ,并且需要远端开启rsyncd
#!/bin/bash


watch_dir=/test/# 本地被监控目录
user="egon"# 虚拟用户
export RSYNC_PASSWORD=123# 虚拟用户密码
module="xxx"# 远程模块名
ip=192.168.12.39# 远程主机ip
# 先整体同步一次
rsync -azc --delete ${watch_dir} ${user}@${ip}::${module}
# 切换到被监控目录下,然后用inotifywait监控./目录,这样后期就可以用-R选项同步新增的子目录
cd $watch_dir
/usr/bin/inotifywait -mrq --timefmt \'%Y-%m-%d %H:%M:%S\' --format \'%w%f:%Xe:%T\' -e create,delete,modify,move,attrib,close_write ./ \\
--exclude=".*.swp" | \\
while read line
do
# $line的输出format为:文件路径:事件:时间
FILE=$(echo $line | awk -F: \'{print $1}\')# 获取文件的绝对路径
EVENT=$(echo $line | awk -F: \'{print $2}\') # 获取监控的事件
# 监控到对文件的下述行为后,只把文件同步到远端
if [[ $EVENT =< sub> \'CREATE\' ]] || [[ $EVENT =< /sub> \'MODIFY\' ]] || [[ $EVENT =< sub> \'CLOSE_WRITE\' ]] || [[ $EVENT =< /sub> \'MOVED_TO\' ]] || [[ $EVENT =< sub> \'ATTRIB\' ]]; then
rsync -azcR ${FILE} ${user}@${ip}::${module}
fi


# 监控到涉及到目录的改动,将目录同步到远端,例如用dirname ${FILE}获取目录
if [[ $EVENT =< /sub> \'DELETE\' ]] || [[ $EVENT =~ \'MOVED_FROM\' ]]; then
rsync -azcR --delete $(dirname ${FILE}) ${user}@${ip}::${module} & > /dev/null
fi
done &
# 末尾的& 符号,代表在子shell中提交命令,这样进程的ppid就变为1,当前窗口关闭,该进程依然存活

远程(配置好rsync守护进程,模块为xxx,虚拟用户名egon,密码123),执行下述命令检测同步情况
while true; do ls /egon_bak; sleep 0.5; clear; done


    推荐阅读