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