1、雙向同步:unison+inotify
2、單向同步:rsync+inotify

python版的pyinotify
本文介紹第二種方法:
1、Inotify 是一個 Linux特性,它監控文件系統操作,比如讀取、寫入和創建。Inotify 反應靈敏,用法非常簡單,並且比 cron 任務的繁忙輪詢高效得多。學習如何將 inotify 集成到您的應用程序中,並發現一組可用來進一步自動化系統治理的命令行工具。inotify是一種強大的,細粒度的,異步文件系統時間監控機制,它可以替代crond實現與rsync的觸發式文件同步,從而監控文件系統中添加,刪除,修改,移動等細粒事件,從LINUX 2.6.13起,就已加入了對inotify的支持,所以我們只需要安裝一個第三方軟件inotify-tools即可管理此服務
2、inotify安裝:
官網:http://inotify.aiken.cz/?section=inotify&page=download&lang=en
里面就兩個C語言的頭文件inotify.h和inotify-syscalls.h
linux內核2.6.13以后開始支持這個特性,查看支持情況:[admin@19-56 ~]$ ls -lsart /proc/sys/fs/inotify/

上圖表示是支持的
3、inotify-tools安裝:其實就是inotify的命令行工具包,這樣你就可以通過命令行使用inotify特性
官網:https://github.com/rvoicilas/inotify-tools
https://github.com/rvoicilas/inotify-tools/wiki
inotify-tools is a C library and a set of command-line programs for Linux providing a simple interface to inotify. These programs can be used to monitor and act upon filesystem events.
inotify-tools安裝完成之后會有兩個命令,inotifywait 和 inotifywatch。inotifywait用於等待文件或者文件集上的一個特定事件,可以監控任何文件或者目錄位置,並且可以遞歸地監控整個目錄樹;inotifywatch 用於收集被監控的文件系統統計數據,包括每個inotify事件發生多少次等信息。
源碼安裝:./configure --prefix=/usr && make && su -c 'make install'
yum安裝:yum install -y inotify-tools
4、inotifywait -h查看inotifywait的幫助信息,常用選項(options)
-r|--recursive Watch directories recursively. 遞歸查詢目錄
-m|--monitor Keep listening for events forever. Without
this option, inotifywait will exit after one
event is received. 始終監控
-q|--quiet Print less (only print events). 打印較少信息,僅打印監控相關信息
常用事件(Events):
modify file or directory contents were written
create file or directory created within watched directory
delete file or directory deleted within watched directory
5、rsync -h查看rsync的幫助信息
-v, --verbose increase verbosity
-a, --archive archive mode; equals -rlptgoD (no -H,-A,-X)
--delete delete extraneous files from destination dirs 意思是刪除目的目錄多余源目錄的內容。這樣源目錄和目的目錄的內容才能一致,否則,目的目錄的內容不斷增加。保持兩個目錄同步增加和刪除
6、重點來了,配置文件
| host | ip | status | kernel | bit | file |
| A | 192.168.10.220 |
master | x86_64 | 64 | /tmp |
| B | 192.168.10.221 |
slave | x86_64 | 64 | /tmp |
注意,不要把容易變化又不是監控目標的東西放到監控目錄里,這樣的話,就不會頻繁產生同步操作。更加需要注意的是,不要把下文的日志記錄放到監控目錄里,這樣就產生了死循環:開始同步,產生日志,日志文件發生變化,繼續同步,再次產生日志,日志文件再次發生變化,再次同步……
一、主服務器A:
建立密碼認證文件
[root@nginx rsync]# echo "rsync-pwd" >/usr/local/rsync/rsync.pwd
其中rsync-pwd可以自己設置密碼,rsync.passwd名字也可以自己設置
[root@nginx rsync]# chmod 600 rsync.passwd
無論是為了安全,還是為了避免出現以下錯誤,密碼文件都需要給600權限
創建rsync復制腳本 此項功能主要是將master端的目錄/tmp里的內容,如果修改了(無論是添加、修改、刪除文件)能夠通過inotify監控到,並通過rsync實時的同步給client的/tmp里,下面是通過shell腳本實現的。
#!/bin/bash host=192.168.10.221 #slave地址 src=/tmp/ #被監控目錄 des=web user=webuser /usr/local/inotify/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 -va --delete --progress --password-file=/usr/local/rsync/rsync.passwd $src $user@$host::$des echo "${files} was rsynced" >>/tmp/rsync.log 2>&1 done
如果把rsync.log的放到tmp(備份的目錄)就會發送一直復制的問題,所以建議各位吧rsync的日志放到其他的目錄下(非備份目錄)。
其中host是slave的ip,src是master端要實時監控的目錄,des是認證的模塊名,需要與slave一致,user是建立密碼文件里的認證用戶。
把這個腳本命名為rsync.sh,放到監控的目錄里,比如我的就放到/tmp下面,並給予764權限
[root@nginx tmp]# chmod 764 rsync.sh
然后運行這個腳本
[root@nginx tmp]# sh /tmp/rsync.sh &
請記住,只有在備份服務器client端的rsync安裝並啟動rsync之后,在啟動rsync.sh腳本,否則有時候會滿屏出現:
rsync: failed to connect to 192.168.10.221: Connection refused (111)
rsync error: error in socket IO (code 10) at clientserver.c(107) [sender=2.6.8]
我們還可以把rsync.sh腳本加入到開機啟動項里
[root@nginx tmp]# echo "/tmp/rsync.sh" >> /etc/rc.local
二、備份服務器(slave)
建立用戶與密碼認證文件
[root@nginx-backup rsync-3.0.9]# echo "webuser:rsync-pwd" > /usr/local/rsync/rsync.passwd
請記住,在master端建立的密碼文件,只有密碼,沒有用戶名;而在備份服務端slave里建立的密碼文件,用戶名與密碼都有。
[root@nginx-backup rsync]# chmod 600 rsync.passwd 需要給密碼文件600權限
建立rsync配置文件
uid = root gid = root use chroot = no max connections = 10 strict modes = yes pid file = /var/run/rsyncd.pid lock file = /var/run/rsync.lock log file = /var/log/rsyncd.log [web] path = /tmp/ #同步的目的目錄 comment = web file ignore errors read only = no write only = no hosts allow = 192.168.10.220 hosts deny = * list = false uid = root gid = root auth users = webuser secrets file = /usr/local/rsync/rsync.pwd
其中web是master服務端里的認證模塊名稱,需要與主服務器里的一致,以上的配置我的自己服務器里的配置,以供參考。
把配置文件命名為rsync.conf,放到/usr/local/rsync/目錄里
啟動rsync
[root@nginx-backup rsync]# /usr/local/rsync/bin/rsync --daemon --config=/usr/local/rsync/rsync.conf
我們可以把rsync腳本加入到開機啟動項里
現在rsync與inotify在master端安裝完成,rsync在備份服務器slave端也安裝完成
參考:http://www.showerlee.com/archives/678
http://www.jb51.net/article/57011.htm
20181117更新:
注意點:
1、rsync+inotifywait的同步模式是阻塞模式,一定放到后台執行,不要影響其他任務執行
2、rc.local啟動的任務賬號都是root賬號,所以注意對文件的讀寫和執行權限
3、啟動日志:/var/log/boot.log,可以通過這個日志查看rc.local里的開機啟動任務啟動情況,是否有異常
4、只可以同步目錄和目錄下的文件,但是不可以直接同步文件
目的:把服務器A的兩個目錄的所有變化同步到服務器B
先上服務器配置A
rc.local配置:
#!/bin/sh -x # # This script will be executed *after* all the other init scripts. # You can put your own initialization stuff in here if you don't # want to do the full Sys V style init stuff. exec 1>/tmp/rc.local.log 2>&1 # send stdout and stderr from rc.local to a log file rc.local的日志默認是在/var/log/boot.log里的,這里把它的日志寫到/tmp/rc.local.log中 set -x # tell sh to display commands before execution touch /var/lock/subsys/local # 作用是確保rc.local不會被執行兩次 /bin/sh /usr/local/rsync/rsyncJobs.sh & # 這里一定要加 & 符號,因為這個同步任務是個阻塞的任務,讓它在后台執行,這樣可以繼續執行其他開機啟動項 /bin/sh /usr/local/rsync/rsyncNodes.sh & # 上面加了后台執行符號 &,這個任務才會執行
目錄一的rsyncJobs.sh配置
host=服務器B的IP
srcJobs=/var/lib/jenkins/jobs/ # 被監控的目錄以及遞歸的目錄和文件,但是不可以直接寫某個具體的文件
desJobs=jobs # 目的
user=webuser # 下面配置的作用是監控目錄/var/lib/jenkins/jobs/的任何變化,然后同步到目的地
inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $srcJobs \
| while read files
do
sleep 5
rsync -va --delete --progress --password-file=/usr/local/rsync/rsync.pwd $srcJobs $user@$host::$desJobs
echo "${files} was rsynced" >> /tmp/rsyncJobs.log 2>&1 # 把同步文件的簡要信息放在這里,大部分相信信息存在/tmp/rc.local.log里
done
目錄二的rsyncNodes.sh配置:
#!/bin/bash host=服務器B的IP srcNodes=/var/lib/jenkins/nodes/ desNodes=nodes user=webuser
# inotifwait的作用是監控文件的變化,然后通知rsync進行同步工作 inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $srcNodes \ | while read files do sleep 5 rsync -va --delete --progress --password-file=/usr/local/rsync/rsync.pwd $srcNodes $user@$host::$desNodes # --delete刪除目標文件比源文件多的文件 echo "${files} was rsynced" >> /tmp/rsyncNodes.log 2>&1 done
密碼的rsync.pwd配置:
rsync-pwd # 只有密碼
服務器B配置:
rc.local
#!/bin/sh -x # # This script will be executed *after* all the other init scripts. # You can put your own initialization stuff in here if you don't # want to do the full Sys V style init stuff. # 放在rc.local多次執行 touch /var/lock/subsys/local
# 開啟rsync服務進程,等待服務器A發起的同步任務 rsync --daemon --config=/usr/local/rsync/rsync.conf
rsync.conf配置
uid=admin # 決定被同步的文件到服務器A上的用戶 gid=admin # 決定被同步的文件到服務器A上的用戶組 use chroot=no max connections=10 strict modes=yes pid file=/usr/local/rsync/rsyncd.pid # 有的時候啟動不了,是因為kill -9后,pid文件還存在。自動生成 lock file=/usr/local/rsync/rsyncd.lock # 有的時候新增加的目錄或者修改的配置不生效,是因為這個配置文件沒有更新,可以刪除下,它會自動生成 log file=/usr/local/rsync/rsyncd.log # 服務器B的rsync服務日志;自動生成 [jobs] # 目錄一的配置 path=/var/lib/jenkins/jobs/ # 服務器A的目錄一的位置,可以是任意目錄,不需要和服務器A的目錄保持一致 comment=web file ignore errors read only=no write only=no hosts allow= 服務器A的IP # 允許連接的IP hosts deny=* list=false uid=admin gid=admin auth users=webuser secrets file=/usr/local/rsync/rsync.pwd [nodes] # 目錄二的配置 path=/var/lib/jenkins/nodes/ # 目錄二在服務器B上的位置 comment=web file ignore errors read only=no write only=no hosts allow=服務器A的IP hosts deny=* list=false uid=admin gid=admin auth users=webuser secrets file=/usr/local/rsync/rsync.pwd
密碼的rsync.pwd的配置
webuser:rsync-pwd # 用戶名:密碼
啟動日志:/var/log/boot.log
rsync -azv --delete --exclude .svn --exclude "compile" --exclude "session_cache" --exclude "web"
/cygdrive/c/www/test/trunk/ username@IP:/home/test/
這里要說的是,同步的時候排除多個文件/文件夾的做法是:
--exclude "文件夾名字(1.唯一的時候,可以直接用文件/文件夾名 2.用絕對路徑)"
以下示例,排除3個文件夾:
--exclude .svn --exclude "compile" --exclude "session_cache"
rsync常用參數:
--delete 刪除目標文件比源文件多余的文件
--exclude 排除文件(文件不會被同步)
下面使用nload -u M觀察到的同步效果圖。使用左右方向鍵可以切換觀察的接口

