rsync + inotify 實現檔案實時雙向自動同步
更多技術文章,請關注:github.com/yongxinz/te…
簡介
隨著應用系統規模的不斷擴大,對資料的安全性和可靠性也提出更好的要求,rsync 在高階業務系統中也逐漸暴露出了很多不足。
首先,rsync 在同步資料時,需要掃描所有檔案後進行比對,進行差量傳輸。如果檔案數量達到了百萬甚至千萬量級,掃描所有檔案將是非常耗時的,並且正在發生變化的往往是其中很少的一部分,這是非常低效的方式。
其次,rsync 不能實時的去監測、同步資料,雖然它可以通過 linux 守護程式的方式進行觸發同步,但是兩次觸發動作一定會有時間差,這樣就導致了服務端和客戶端資料可能出現不一致,無法在應用故障時完全的恢復資料。
基於以上兩種情況,可以使用 rsync+inotify 的組合來解決,可以實現資料的實時同步。
inotify 是一種強大的、細粒度的、非同步的檔案系統事件控制機制。linux 核心從 2.6.13 起,加入了 inotify 支援。通過 inotify 可以監控檔案系統中新增、刪除、修改、移動等各種事件,利用這個核心介面,第三方軟體就可以監控檔案系統下檔案的各種變化情況,而 inotify-tools 正是實施監控的軟體。在使用 rsync 首次全量同步後,結合 inotify 對源目錄進行實時監控,只要有檔案變動或新檔案產生,就會立刻同步到目標目錄下,非常高效實用。
rsync
安裝
yum -y install rsync
複製程式碼
原始碼方式安裝這裡不介紹了。
常用引數
-v :展示詳細的同步資訊
-a :歸檔模式,相當於 -rlptgoD
-r :遞迴目錄
-l :同步軟連線檔案
-p :保留許可權
-t :將原始檔的"modify time"同步到目標機器
-g :保持檔案屬組
-o :保持檔案屬主
-D :和--devices --specials一樣,保持裝置檔案和特殊檔案
-z :傳送資料前,先壓縮再傳輸
-H :保持硬連結
-n :進行試執行,不作任何更改
-P same as --partial --progress
--partial :支援斷點續傳
--progress :展示傳輸的進度
--delete :如果原始檔消失,目標檔案也會被刪除
--delete-excluded :指定要在目的端刪除的檔案
--delete-after :預設情況下,rsync是先清理目的端的檔案再開始資料同步;如果使用此選項,則rsync會先進行資料同步,都完成後再刪除那些需要清理的檔案。
--exclude=PATTERN :排除匹配PATTERN的檔案
--exclude-from =FILE :如果要排除的檔案很多,可以統一寫在某一檔案中
-e ssh :使用SSH加密隧道傳輸
複製程式碼
部署使用
- 伺服器A: 192.168.0.1
- 伺服器B: 192.168.0.2
這裡有兩臺 linux 伺服器,我們可以先假定 A 作為服務端,B 作為客戶端。
1、服務端配置:
修改服務端的配置檔案:/etc/rsyncd.conf
,內容如下:
# rsync 守護程式的使用者
uid = www
# 執行 rsync 守護程式的組
gid = www
# 允許 chroot,提升安全性,客戶端連線模組,首先 chroot 到模組 path 引數指定的目錄下,chroot 為 yes 時必須使用 root 許可權,且不能備份 path 路徑外的連結檔案
use chroot = yes
# 只讀
read only = no
# 只寫
write only = no
# 設定白名單,可以指定IP段(172.18.50.1/255.255.255.0),各個Ip段用空格分開
hosts allow = 192.168.0.2
hosts deny = *
# 允許的客戶端最大連線數
max connections = 4
# 歡迎檔案的路徑,非必須
motd file = /etc/rsyncd.motd
# pid檔案路徑
pid file = /var/run/rsyncd.pid
# 記錄傳輸檔案日誌
transfer logging = yes
# 日誌檔案格式
log format = %t %a %m %f %b
# 指定日誌檔案
log file = /var/log/rsync.log
# 剔除某些檔案或目錄,不同步
exclude = lost+found/
# 設定超時時間
timeout = 900
ignore nonreadable = yes
# 設定不需要壓縮的檔案
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
# 模組,可以配置多個
[sync_file]
# 模組的根目錄,同步目錄,要注意許可權
path = /home/test
# 是否允許列出模組內容
list = no
# 忽略錯誤
ignore errors
# 新增註釋
comment = ftp export area
# 模組驗證的使用者名稱稱,可使用空格或者逗號隔開多個使用者名稱
auth users = sync
# 模組驗證密碼檔案 可放在全域性配置裡
secrets file = /etc/rsyncd.secrets
複製程式碼
編輯 /etc/rsyncd.secrets
檔案,內容如下:
### rsyncd.secrets 檔案的配置
# 使用者名稱:密碼
sync:123456
複製程式碼
編輯 /etc/rsyncd.motd
檔案,內容如下:
### rsyncd.motd 檔案配置
++++++++++++++++++
sync zhang : rsync start
++++++++++++++++++
複製程式碼
設定檔案許可權,這一步不能少:
chmod 600 /etc/rsyncd.secrets
複製程式碼
啟動:
rsync --daemon --config=/etc/rsyncd.conf
複製程式碼
加入開機自啟:
echo 'rsync --daemon --config=/etc/rsyncd.conf' >> /etc/rc.d/rc.local
複製程式碼
2、客戶端配置:
建立密碼檔案 /etc/rsyncd.pass
,直接寫密碼即可,內容如下:
### rsyncd.pass 檔案的配置
123456
複製程式碼
設定檔案許可權,這一步不能少:
chmod 600 /etc/rsyncd.pass
複製程式碼
現在就可以在客戶端執行命令來同步檔案了。
從 服務端=>客戶端 同步資料:
rsync -avzP --delete sync@192.168.0.1::sync_file /home/test --password-file=/etc/rsyncd.pass
複製程式碼
從 客戶端=>服務端 同步資料:
rsync -avzP --delete /home/test sync@192.168.0.1::sync_file --password-file=/etc/rsyncd.pass
複製程式碼
到目前為止,rsync 就配置完成了,如果想實現雙向同步,只要將 B 配置成服務端,A 配置成客戶端,分別啟對應的服務即可。
接下來介紹 inotify 監控檔案變動,來實現實時同步。
inotify
安裝
yum install -y inotify-tools
複製程式碼
常用引數
1、inotifywait 引數說明:
-m,–monitor:始終保持事件監聽狀態 # 重要引數
-r,–recursive:遞迴查詢目錄 # 重要引數
-q,–quiet:只打印監控事件的資訊 # 重要引數
–excludei:排除檔案或目錄時,不區分大小寫
-t,–timeout:超時時間
–timefmt:指定時間輸出格式 # 重要引數
–format:指定時間輸出格式 # 重要引數
-e,–event:後面指定刪、增、改等事件 # 重要引數
複製程式碼
2、inotifywait events 事件說明:
access:讀取檔案或目錄內容
modify:修改檔案或目錄內容
attrib:檔案或目錄的屬性改變
close_write:修改真實檔案內容 # 重要引數
close_nowrite:檔案或目錄關閉,在只讀模式開啟之後關閉的
close:檔案或目錄關閉,不管讀或是寫模式
open:檔案或目錄被開啟
moved_to:檔案或目錄移動到
moved_from:檔案或目錄從移動
move:移動檔案或目錄移動到監視目錄 # 重要引數
create:在監視目錄下建立檔案或目錄 # 重要引數
delete:刪除監視目錄下的檔案或目錄 # 重要引數
delete_self:檔案或目錄被刪除,目錄本身被刪除
unmount:解除安裝檔案系統
複製程式碼
常用命令
1、建立事件
inotifywait -mrq /data --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件資訊: %e" -e create
複製程式碼
2、刪除事件
inotifywait -mrq /data --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件資訊: %e" -e delete
複製程式碼
3、修改事件
inotifywait -mrq /data --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件資訊: %e" -e close_write
複製程式碼
指令碼監控
#!/bin/bash
Path=/home/test
Server=192.168.0.2
User=sync
module=sync_file
monitor() {
/usr/bin/inotifywait -mrq --format '%w%f' -e create,close_write,delete $1 | while read line; do
if [ -f $line ]; then
rsync -avz $line --delete ${User}@${Server}::${module} --password-file=/etc/rsyncd.pass
else
cd $1 &&
rsync -avz ./ --delete ${User}@${Server}::${module} --password-file=/etc/rsyncd.pass
fi
done
}
monitor $Path;
複製程式碼
直接將指令碼在後臺啟動,就可以監控檔案的變化了,從而實現伺服器之間的檔案同步。
那麼,如果想同步多個目錄該怎麼辦呢?我能想到的辦法就是寫多個 shell 指令碼,每個指令碼負責一個目錄,但總感覺這種方法不是很好,大家有何高見?
參考文章:
www.jianshu.com/p/bd3ae9d80…
www.mengzhaoxu.xyz/2018/12/24/…
www.cnblogs.com/bigberg/p/7…
cloud.tencent.com/developer/a…
blog.csdn.net/chenghuikai…
www.devopssec.cn/2018/08/23/…