本文共 4812 字,大约阅读时间需要 16 分钟。
rsync 是Linux 下的一个文件同步利器,以高效的增量传输而闻名,适用于同步,备份等多个场合。几乎所有的Linux 发行版都收录了该软件,安装非常容易,以CentOS 6.4为例:
1 | yum install rsync |
rsync 有个特别之处,既可以作为服务端在后台运行,也可以作为客户端去连接服务器,甚至可以抛弃服务端,直接在本地文件系统上进行同步。
本文讲述 inotify+rsync 打造文件实时同步系统,先讲讲它与传统的rsync 服务器之间的区别,这点非常重要,很少有人提及这个,以至于新手在配置inotify+rsync 产生疑惑。
通常而言,rsync 作为服务端监听在873端口,等待客户端来连接,对应的模式是一个服务端,多个客户端,比如
1 | rsync -avz --delete 10.1.1.11::web/ /var/www/ |
上面的例子中,只要规则允许,任何一个可以连接到10.1.1.11的机器,都可以去同步它。这种场合下,服务端10.1.1.11 是一般是权威内容的发布器,因此其内容是只读的。
在 inotify+rsync 场合中,工作模式是一个客户端,多个服务端,客户端掌握了权威内容,主动向服务端推送内容(服务端必须是可写的),例子如下:
1 2 3 | rsync -avz -- delete / var /www/ 10.1 . 1.11 ::web/ rsync -avz -- delete / var /www/ 10.1 . 1.12 ::web/ rsync -avz -- delete / var /www/ 10.1 . 1.13 ::web/ |
上面的例子就是,客户端将/var/www里的网页内容,主动推向3个服务端。
inotify 是个内核工具,能够监视文件目录的变化,客户端通过inotify 得知变化后立即主动将内容写入服务端。
所谓的原理就这么多了,关于inotify 的东西,别人都讲清楚了,不详述。
配置服务端
1 、创建并编辑文件 /etc/rsyncd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | uid = root gid = root address = 10.1.1.11 use chroot = no read only = no max connections = 512 log file = /var/log/rsyncd .log log format = %t %a %m %f %b pid file = /var/run/rsyncd .pid lock file = /var/run/rsyncd .lock [web] path= /var/www/ list = yes ignore errors = yes hosts allow = 10.1.1.20 hosts deny = * |
2、启动rsync 服务端
1 | rsync --daemon -4 |
将上面一句命令加入/etc/rc.local ,可以让rsync 随系统启动。
3、配置防火墙,开启873端口
1 | /sbin/iptables -A INPUT -s 10.1.1.20 -p tcp --dport 873 -j ACCEPT |
4、服务端配置完成,如果有多个服务端,请依葫芦画瓢。
配置客户端
1、安装rsync
1 | yum install rsync |
2、安装inotify-tools
1 | yum install inotify-tools --enablerepo=epel |
3、写个脚本,一旦 inotify 发现变化,立即触发rsync 将变化推送到服务端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/env bash set -e src= /var/www/ web01=10.1.1.11 web02=10.1.1.12 web03=10.1.1.13 /usr/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' -- format '%T %w%f%e' \ -e modify,delete,create,attrib $src \ | while read files do /usr/bin/rsync -vzrtopg --delete --progress $src $web01::web/ /usr/bin/rsync -vzrtopg --delete --progress $src $web02::web/ /usr/bin/rsync -vzrtopg --delete --progress $src $web03::web/ echo $files have been pushed to all web servers. done |
4、启动脚本,并在后台运行,或者让它开机启动
1 2 3 | chmod 755 /opt/inotify-rsync .sh /opt/inotify-rsync .sh& echo "/opt/inotify-rsync.sh&" >> /etc/rc . local |
update 2014-04-18
上面的脚本可控性比较差,于是重新写了一个init脚本 。
/etc/init.d/realsync,权限755,支持chkconfig开机启动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #!/bin/sh # # realsync - realtime sync with remote directory. # # chkconfig: - 85 15 # description: realsync is a shell script which join "rsync" and "inotifywait" together \ # to make realtime sync with remote directory. ### BEGIN INIT INFO # Provides: realsync # Required-Start: $local_fs $remote_fs $network # Required-Stop: $local_fs $remote_fs $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: realtime sync with remote directory ### END INIT INFO # Source function library. . /etc/rc .d /init .d /functions exec = "/usr/bin/inotifywait" prog=$( basename $ exec ) lockfile= /dev/shm/ $prog opts= "-mrqsd -e close_write,modify,create,attrib -o $lockfile" #local directory to monitor local_dir= "/var/www" #remote directory to rsync remote_dir= "10.1.1.11::web" start() { echo -n $ "Starting $prog: " touch $lockfile daemon $ exec $opts $local_dir while [[ -s $lockfile ]]; do rsync -aqu $local_dir/ $remote_dir/ > $lockfile done retval=$? echo [ $retval - eq 0 ] return $retval } stop() { echo -n $ "Stopping $prog: " killproc $prog retval=$? echo [ $retval - eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; status) status $prog ;; *) echo $ "Usage: $0 {start|stop|status|restart}" exit 2 esac |
开机启动
1 | chkconfig realsync on |
至此,inotify + rsync 全部搞定。
update 2016-01-11
为了让脚本看起来更像一个程序,写个稍稍“另类”一点的脚本。
1、inotifywait只监控一次event便退出,接着执行rsync命令
2、如果5分钟(300秒)内没有监控到event,inotifywait会超时退出,强制执行后面的rsync命令
3、写日志,睡眠1秒,进入下一个循环
4、想要中断循环,删除一个lock文件即可,见stop参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #!/usr/bin/env bash #set -x name=realsync lockfile= /var/lock/subsys/realsync .lock # Source function library. . /etc/rc .d /init .d /functions case "$1" in start) echo -n $ "Starting $name: " touch $lockfile while true ; do [ -e $lockfile ] || break /usr/bin/inotifywait -rqqs -t 300 --event create,modify,delete,attrib,close_write /var/www/ /usr/bin/rsync -aqu /var/www/ 192.168.0.1::web/ sleep 1 mkdir -p /var/log/realsync echo "$(date +'%F %T') realsync works." >> /var/log/realsync/realsync .log-$( date +%F) done & echo ;; stop) echo -n $ "Stopping $name: " rm -rf $lockfile pkill inotifywait echo ;; *) echo $ "Usage: $0 {start|stop}" exit 2 esac |