1. 程式人生 > 程式設計 >rsync + inotify 實現檔案實時雙向自動同步

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/…