天天看点

inotify + rsync 打造文件实时同步

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&amp;</code>

<code>echo</code> <code>"/opt/inotify-rsync.sh&amp;"</code> <code>&gt;&gt;</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>&gt; $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 ] &amp;&amp; </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>&gt;&gt; </code><code>/var/log/realsync/realsync</code><code>.log-$(</code><code>date</code> <code>+%F)</code>

<code>        </code><code>done</code><code>&amp;</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,如需转载请自行联系原作者

继续阅读