天天看點

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,如需轉載請自行聯系原作者

繼續閱讀