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