1. 程式人生 > >Rsync+inotify實現檔案實時同步#附shell指令碼

Rsync+inotify實現檔案實時同步#附shell指令碼

強烈推薦先仔細看此文

https://segmentfault.com/a/1190000002427568

實驗環境

centos 7.3
vm2:192.168.221.128 同步伺服器
vm1:192.168.221.129 上傳伺服器
關閉seliunx
關閉防火牆

同步伺服器vm2的配置

yum install rsync
建立rsyncd.conf配置檔案:
log file = /var/log/rsyncd.log
pidfile = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
secrets file = /etc/rsync.pass #使用者認證配置檔案,裡面儲存使用者名稱稱和密碼,後面會建立這個檔案
motd file = /etc/rsyncd.Motd #rsync啟動時歡迎資訊頁面檔案位置(檔案內容自定義)

[Sync] #同步模組名稱
path = /data/wwwroot/sync/ #rsync服務端資料目錄路徑(最後面的“/”很重要)
comment = Sync
uid = root
gid = root
port=873
use chroot = no
read only = no
list = no #不顯示rsync服務端資源列表
max connections = 200
timeout = 600
auth users = root #執行資料同步的使用者名稱,可以設定多個,用英文狀態下逗號隔開
hosts allow = 192.168.221.129#允許進行資料同步的客戶端IP地址,可以設定多個,用英文狀態下逗號隔開
hosts deny = 0.0.0.0/32
建立使用者認證檔案
#vim /etc/rsync.pass
user1:123456 #格式,使用者名稱:密碼,可以設定多個,每行一個使用者名稱:密碼
設定檔案許可權
chmod 600 /etc/rsyncd.conf #設定檔案所有者讀取、寫入許可權
chmod 600 /etc/rsync.pass #設定檔案所有者讀取、寫入許可權
啟動rsync
#/usr/bin/rsync --daemon --config=/etc/rsyncd.conf
daemon模式:使用TCP直接連線rsync daemon。當源路徑或目的路徑的主機名後面包含兩個冒號,或使用rsync://URL時使用這種模式,無需遠端shell,但必須在一臺機器上啟動rsync daemon,預設埠873,這裡可以通過rsync --daemon使用獨立程序的方式,或者通過xinetd超級程序來管理rsync後臺程序。
當rsync作為daemon執行時,它需要一個使用者身份。如果你希望啟用chroot,則必須以root的身份來執行daemon,監聽埠,或設定檔案屬主;如果不啟用chroot,也可以不使用root使用者來執行daemon,但該使用者必須對相應的模組擁有讀寫資料、日誌和lock file的許可權。當rsync以daemon模式執行時,它還需要一個配置檔案——rsyncd.conf。修改這個配置後不必重啟rsync daemon,因為每一次的client連線都會去重新讀取該檔案。

釋出伺服器vm1的配置

#yum install rsync
建立認證密碼檔案
vim /etc/passwd.txt
123456 #只需要填寫密碼即可,不用像rsync.pass需要用“使用者:密碼”的格式

chmod 600 /etc/passwd.txt #設定檔案許可權,只設置檔案所有者具有讀取、寫入許可權即可
驗證同步傳輸

在釋出伺服器vm1上操作

#將釋出伺服器vm1的檔案同步到同步伺服器vm2

rsync -avH --port=873 --progress --delete /data/wwwroot/sync/ [email protected]::Sync --password-file=/etc/passwd.txt

#將同步伺服器vm2的檔案同步到釋出伺服器vm1

rsync -avH --port=873 --progress --delete 
[email protected]
::Sync --password-file=/etc/passwd.txt /data/wwwroot/sync

!!!這裡在正式環境上操作一定要注意兩種同步命令的差別,不然會導致檔案刪除

- 刪除/root/下的檔案不會同步刪除/tmp/rsync_bak,除非加入--delete選項
- 檔案訪問時間等屬性、讀寫等許可權、檔案內容等有任何變動,都會被認為修改
- 目標目錄下如果檔案比源目錄還新,則不會同步
- 源路徑的最後是否有斜槓有不同的含義:有斜槓,只是複製目錄中的檔案;沒有斜槓的話,不但要複製目錄中的檔案,還要複製目錄本身

安裝使用inotify

rsync不能實時的去監測、同步資料,雖然它可以通過crontab方式進行觸發同步,但是兩次觸發動作一定會有時間差,這樣就導致了服務端和客戶端資料可能出現不一致,無法在應用故障時完全的恢復資料。基於以上原因,rsync+inotify組合出現了

1、檢視伺服器核心是否支援inotify
#ll /proc/sys/fs/inotify #列出檔案目錄,出現下面的內容,說明伺服器核心支援inotify
-rw-r--r-- 1 root root 0 Mar 7 02:17 max_queued_events
-rw-r--r-- 1 root root 0 Mar 7 02:17 max_user_instances
-rw-r--r-- 1 root root 0 Mar 7 02:17 max_user_watches
注:Linux下支援inotify的核心最小為2.6.13

2、安裝inotify-tools
#wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz
#tar zxvf inotify-tools-3.14.tar.gz
#cd inotify-tools-3.14
#./configure --prefix=/usr/local/inotify&& make && make install


3、修改inotify預設引數(inotify預設核心引數值太小)
檢視系統預設引數值
sysctl -a | grep max_queued_events
結果是:fs.inotify.max_queued_events = 16384
sysctl -a | grep max_user_watches
結果是:fs.inotify.max_user_watches = 8192
sysctl -a | grep max_user_instances
結果是:fs.inotify.max_user_instances = 128

#vi /etc/sysctl.conf #新增以下程式碼,修改引數
fs.inotify.max_queued_events=99999999
fs.inotify.max_user_watches=99999999
fs.inotify.max_user_instances=65535

4、sysctl -p生效,系統重啟後也可以正常工作

引數說明:
max_queued_events:
inotify佇列最大長度,如果值太小,會出現"** Event Queue Overflow **"錯誤,導致監控檔案不準確
max_user_watches:
要同步的檔案包含多少目錄,可以用:find /home_test -type d | wc -l 統計,必須保證max_user_watches值大於統
計結果(這裡/home_test為同步檔案目錄)
max_user_instances:
每個使用者建立inotify例項最大值
inotify-tools

inotify-tools是為linux下inotify檔案監控工具提供的一套C的開發介面庫函式,同時還提供了一系列的命令列工具,這些工具可以用來監控檔案系統的事件。 inotify-tools是用c編寫的,除了要求核心支援inotify外,不依賴於其他。inotify-tools提供兩種工具,一是inotifywait,它是用來監控檔案或目錄的變化,二是inotifywatch,它是用來統計檔案系統訪問的次數。

rsync組合inotify-tools完成實時同步

這一步的核心其實就是在客戶端建立一個指令碼rsync.sh,適用inotifywait監控本地目錄的變化,觸發rsync將變化的檔案傳輸到遠端備份伺服器上

建立排除在外不同步的檔案列表
排除不需要同步的檔案或目錄有兩種做法:
第一種是inotify監控整個目錄,在rsync中加入排除選項,簡單
第二種是inotify排除部分不監控的目錄,同時rsync中也要加入排除選項,可以減少不必要的網路頻寬和CPU消耗
我們選擇第二種
inotifywait排除

這個操作在客戶端進行,假設/tmp/src/mail/2014/以及/tmp/src/mail/2015/cache/目錄下的所有檔案不用同步,所以不需要監控,/tmp/src/下的其他檔案和目錄都同步

其實對於開啟的臨時檔案,可以不監聽modify時間而改成監聽close_write

inotifywait排除監控目錄有--exclude

# vi /etc/inotify_exclude.lst:
/tmp/src/pdf
@/tmp/src/2014

使用fromfile格式只能用絕對路徑,不能使用諸如*正則表示式去匹配,@表示排除。
如果要排除的格式比較複雜,必須使用正則,那隻能在inotifywait中加入選項

--exclude '(.*/*\.log|.*/*\.swp)$|^/tmp/src/mail/(2014|201.*/cache.*)'

表示排除/tmp/src/mail/以下的2014目錄,和所有201*目錄下的帶cache的檔案或目錄,以及/tmp/src目錄下所有的以.log或.swp結尾的檔案。

rsync排除

使用inotifywait排除監控目錄的情況下,必須同時使用rsync排除對應的目錄,否則只要有觸發同步操作,必然會導致不該同步的目錄也會同步。與inotifywait類似,rsync的同步也有--exclude和--exclude-from兩種寫法

個人還是習慣將要排除同步的目錄解除安裝單獨的檔案列表裡,便於管理。使用--include-from=FILE時,排除檔案列表用絕對路徑,但FILE裡面的內容請用相對路徑,如:

/etc/rsyncd.d/rsync_exclude.lst:
mail/2014/
mail/201*/201*/201*/.??*
mail??*
src/*.html*
src/js/
src/ext3/
src/2014/20140[1-9]/
src/201*/201*/201*/.??*
membermail/
membermail??*
membermail/201*/201*/201*/.??*

排除同步的內容包括,mail下的2014目錄,類似2015/201501/20150101/下的臨時或隱藏檔案等

觸發指令碼如下:(未加入排除選項)

#bin/bash
#rsync auto sync script with inotify
#2018-2-25 mumengyun
current_date=$(date +%Y%m%d_%H%M%S)
source_path=/data/wwwroot/sync/
log_file=/data/wwwlogs/rsync.log

#rsync
rsync_server=192.168.221.128
rsync_user=root
rsync_pwd=/etc/passwd.txt
rsync_module=Sync
#RSYNC_EXCLUDE='/etc/rsyncd.d/rsync_exclude.list'

#rsync client pwd check
if [ ! -e ${rsync_pwd} ];then
echo -e "rsync client passwod file ${rsync_pwd} does not exist!"
exit 0
fi

for ip in $rsync_server
do
/usr/bin/rsync -auvrtzopgP --port=873 --progress --delete --bwlimit=200 --password-file=${rsync_pwd} ${source_path} ${rsync_user}@$ip::${rsync_module}
done

/usr/local/inotify/bin/inotifywait -mrq --timefmt '%Y/%m/%d-%H:%M:%S' --format '%T %w %f' -e close_write,modify,delete,create,move,attrib ${source_path} | while read file
do
for ip in $rsync_server
do
/usr/bin/rsync -auvrtzopgP --port=873 --progress --delete --bwlimit=200 --password-file=${rsync_pwd} ${source_path} ${rsync_user}@$ip::${rsync_module}
done
done
#inotify log
inotify_fun >> ${log_file} 2>&1 &

--bwlimit=200用於限制傳輸速率最大200kb,因為在實際應用中發現如果不做速率限制,會導致巨大的CPU消耗