Unix下使用inotify+rsync同步文件

之前介绍了rsync同步工具,相比cp、tar等同步工具来说,rsync的确更安全、更迅速,并且支持增量备份。通过rsync可以解决对实时性要求不高的同步需求,比如磁盘文件文件定期备份等。了解rsync
但是rsync也有缺点,首先rsync在同步文件时,先要扫描所有文件进行对比,然后进行差量传输,当文件数量比较大时,比如几百万甚至上千万数量的文件,扫描所有文件是非常耗时的。并且发生改变的文件是非常少的,这是非常高效的。其次,rsync不能时实的去同步、监控数据,虽然它可以通过crontab方式进行触发同步,但是两次触发动作一定会有时间差,这样就导致了服务端和客户端数据可能出现不一致,无法在应用故障时完全的恢复数据。所以,为了提高传输文件的效率、提高实时性,推荐inotify+rsync组合。

7F5705A5-D52C-4CC2-93CC-2B6EFA63BE1E

认识inotify-tools

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

inotify-tools:

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

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

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

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

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

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

我们选择第二种。

inotifywait排除

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

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

 vi /etc/inotify_exclude.lst:
/tmp/src/pdf
@/tmp/src/2014

使用fromfile格式只能用绝对路径,不能使用诸如*正则表达式去匹配,@表示排除。

如果要排除的格式比较复杂,必须使用正则,那只能在inotifywait中加入选项,如–exclude ‘(.*/*\.log|.*/*\.swp)$|^/tmp/src/mail/(2014|201.*/cache.*)’,表示排除/tmp/src/mail/以下的2014目录,和所有201*目录下的带cache的文件或目录,以及/tmp/src目录下所有的以.log或.swp结尾的文件。

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/下的临时或隐藏文件,等。

客户端同步到远程的脚本rsync.sh

#rsync auto sync script with inotify
#2014-12-11 Sean
#variables
current_date=$(date +%Y%m%d_%H%M%S)
source_path=/tmp/src/
log_file=/var/log/rsync_client.log

#rsync
rsync_server=172.29.88.223
rsync_user=sean
rsync_pwd=/etc/rsync_client.pwd
rsync_module=module_test
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即可实时同步目录。

参考

notify-tools

JackSun

JackSun

I'm a coder.

You may also like...

Leave a Reply

Your email address will not be published.