一、概况
1.1、组合起源
Rsync(remote sync),通过rsync可以实现对远程服务器数据的增量备份同步,但rsync本身也有瓶颈,同步数据时采用核心算法对远程服务器目标文件进行比对,只进行差异同步。如果服务器文件数量达到百万甚至千万级别,比对将是非常耗时的。而发生变化的往往是其中很少一部分。inotify的出现,可以缓解rsync不足之处,取长补短。同时也是实现实时同步的一种方式。
1.2、inotify简介
inotify是一种强大的、细粒度的、异步的文件系统事件监控机制,Linux内核从2.6.13起,加入了对inotify的支持,可以通过inotify监控文件系统中添加、修改、移动、删除等各种事件,利用这个接口,第三方软件就可以监控文件系统下文件的各种变化情况。inotify-tools正是实施这样监控的软件。
1.3、结构
当inotify服务器上文件变化时,就会触发将变化的文件传给rsync服务端进行同步。
二、安装
2.1、准备
使用两台Linux机器,一台(A)开启rsync daemon服务进程,在另一台(B)上确保可以执行同步数据过去。
A机器:rsync服务端配置可以参考之前的博文。
B机器测试同步:
echo apache > rsyncd.password chmod 400 rsyncd.password rsync -avPh /tmp/ [email protected]::test --password-file=rsyncd.password
已经同步成功,在A上查看:
2.2、安装inotify-tools
B机器(客户端)上配置:
检查系统是否支持:
下载、安装(inotify-tools 3.14 is the latest version, released on the 7th of March 2010.):
wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz tar zxf inotify-tools-3.14.tar.gz -C /usr/local/src/ cd /usr/local/src/inotify-tools-3.14/ CFLAGS="-fPIC -O3" ./configure --prefix=/usr/local/inotify make -j `cat /proc/cpuinfo | grep processor | wc -l` && make install echo 'export PATH=/usr/local/inotify/bin/:$PATH' > /etc/profile.d/inotify.sh source /etc/profile.d/inotify.sh
三、Rsync+Inotify联合应用
3.1、测试监听事件
mkdir /backup inotifywait -mrq --timefmt "%Y/%m/%d %H:%M" --format "%T %Xe %w%f" -e create,delete,attrib,modify /backup/
这里监控了创建、修改、删除和属性变更的操作。
重新开个窗口在所监控的目录下面进行相关操作:
可以看到操作事件已经被监听到:
3.2、close_write与modify
会有这样一种情况,向inotify监控目录持续与入一个大的文件时,inotify会持续不断的输出该文件的modify信息,对于后面的制作脚本来说,就会不断地触发rsync同步操作,占用大量系统资源。针对这种情况,只需将modify监控事项改为close_write即可。如:
inotifywait -mrq --timefmt "%Y/%m/%d %H:%M" --format "%T %Xe %w%f" -e create,delete,attrib,modify,close_write /backup/
可以很明显的看到,当对文件持续写入时,colse_write只会在写入完成后生成一次事件。
3.3、制作简单脚本
上面的操作我们已可以提取到变化的目前和文件,接下来就是如何使用了。
vim inotify.sh
#!/bin/bash #Author:Chris Red='\033[31m\033[1m' Green='\033[32m\033[1m' Null='\033[0m' #----config---- Bindir=/usr/local/inotify/bin Src=/backup User=apache Host=172.16.220.225 Dst=test Pass=/etc/rsyncd.password #----config---- if [ -x $Bindir/inotifywait ];then inotifywait=$Bindir/inotifywait else echo -e ${Red}command inotifywait cant not fond in ${Bindir}${Null} exit 0 fi if [ ! -f ${Pass} ];then echo -e ${Red}${Pass} does not exist${Null} exit 0 fi cd ${Src} ${inotifywait} -mrq --format "%Xe %w %f" -e create,delete, close_write,attrib ${Src} \ | while read event dir file do if [[ $event =~ 'CREATE' ]] || [[ $event =~ 'CLOSE' ]];then ffile=${dir}${file} fpath=$(echo ${ffile} | sed 's_'$Src'/__') rsync -arzR ${fpath} ${User}@${Host}::${Dst} --password-file=${Pass} > /dev/null 2>&1 fi if [[ $event =~ 'DELETE' ]];then dpath=.$(echo ${dir} | sed 's_'$Src'__') rsync -arzR --delete ${dpath} ${User}@${Host}::${Dst} --password-file=${Pass} > /dev/null 2>&1 fi if [[ $event =~ 'ATTRIB' ]];then ffile=${dir}${file} if [ ! -d ${ffile} ];then rsync -arzR ${fpath} ${User}@${Host}::${Dst} --password-file=${Pass} > /dev/null 2>&1 fi fi done
chmod +x inotify.sh
3.4、测试
A机器(Rsync服务端)上,将准备过程中同步过来的文件删掉,目录留空:
B机器执行上步创建的脚本,为了直观的看到过程,加了-x选项:
bash -x inotify.sh
创建文件:
查看过程:
结果:
执行删除:
四、优化脚本
以上脚本可满足一般使用。但其中存在问题,当处理文件较多,执行较频繁时,将会出现灾难性的问题:如,执行touch {1..1000}其会产生CREATE、ATTRIB事件,这样同一个文件会重复执行2次,1000个文件会循环运行2000次执行rsync;又如,在一个目录下执行了rm -rf *,这样一个目录下有多少文件就要执行多少次,相当“不智能”,而且会耗费大量资源,于是需要优化。
脚本这里就不全发上来了,有兴趣的可以留言索要,下面是部分截图:
脚本看上去虽然比较复杂,但完全可以避免上述情况的发生:inotifywait监控目标目录,当有监视的事件发生时,同时最多生成thread=4个线程进行执行;当事件为create、modify、attrib时,会检测、判断目标文件是否存在,并以Interval=1秒为间隔,若在1秒之内,上次执行传输过同一文件,则此次不执行;当事件为delete时,会将删除文件的上层目录进行同步,会判断目录是否存在,同样会判断在1秒之内是否有执行过此目录的同步。
五、系统参数调整
在/proc/sys/fs/inotify目录下有三个文件,对inotify机制有一定的限制
max_user_watches #设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)
max_user_instances #设置每个用户可以运行的inotifywait或inotifywatch命令的进程数
max_queued_events #设置inotify实例事件(event)队列可容纳的事件数量
默认这三个参数数值为:
主要修改监视文件数量和队列数值:
echo 65536000 > /proc/sys/fs/inotify/max_user_watches echo 327680 > /proc/sys/fs/inotify/max_queued_events
😎 😎 😎 666666