使用 rsync 和 inotify 實現即時備份

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


實時同步的原理

是透過監測文件狀態變化 再 更新被動地更動
監測可以使用inotify-tools命令

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

inotify 是kernal function之一
以下軟體可以呼叫inotify功能

inotify-tools 內建
sersync 第三方
lrsyncd 第三方

inotify 監控 rsync 同步 再使用腳本自動化操作

inotify 監控

安裝inotify-tools在機器1(被備份端)

sudo yum install inotify-tools -y
安裝完後可以使用rpm -ql inotify-tools查看相關工具

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

inotify-tools主要工具

inotifywait : 監測檔案或資料夾發生的事件的次數(包括 開啟 關閉 刪除等)
inotifywatch : 統計發生的事件的次數

進階設置

inotify kernal參數 主要有 max_queued_events、max_user_instances、max_user_watches,分別的作用是:
max_queued_events:
作用:這個參數定義了 inotify 事件隊列中可以排隊的最大事件數量。當事件數量達到這個限制時,新的事件會被丟棄並且內核會發出一個溢出(overflow)事件來通知用戶空間程序。
用途:限制事件隊列的大小以防止過多的事件佔用內存,從而保護系統穩定性。
max_user_instances:
作用:這個參數定義了每個用戶可以創建的 inotify 實例的最大數量。一個 inotify 實例是由調用 inotify_init() 系統調用創建的。
用途:限制每個用戶創建的 inotify 實例數量,以防止資源耗盡攻擊(resource exhaustion attacks)。
max_user_watches:
作用:這個參數定義了每個用戶可以監視的文件或目錄的最大數量。每個 inotify 實例可以監視多個文件或目錄,每個監視都佔用一個 watch descriptor。
用途:限制每個用戶能監視的文件或目錄數量,防止單個用戶佔用過多資源,從而影響系統的其他部分或其他用戶。
基本上只需要確保max_queued_events(預設值16384 較小)足夠大以應付同時發生的大量事件和max_user_instances(預設值8192 較小)

可以透過 cat /proc/sys/fs/inotify/參數名稱 查看 設定值
並使用 vim /etc/sysctl.fonf
加上 fs.inotify.參數名稱=數值 即可設定
例如 fs.inotify.max_user_instances=10000

inotifywait 命令

用法 inotifywait 檔案或資料夾

ex:inotify /data/www/

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

可以監控到 操作touch a.txt,但是命令執行完畢後便結束任務 不會持續監控

可以透過 -m 設置成持續監控

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

圖中呈現了幾種基本操作監控到的事件

inotifywait 常用參數的介紹:

  • -m (monitor): 監控目標路徑的變化,持續運行,直到手動終止。
  • -d (daemonize): 以守護進程方式運行,適合於長期運行的監控任務。
  • -r (recursive): 遞歸監控目標路徑下的所有子目錄。
  • -q (quiet): 靜默模式,只輸出變化事件,不顯示啟動和結束信息。
  • --exclude: 使用正則表達式排除特定文件或目錄(大小寫敏感)。
  • --excludei: 使用正則表達式排除特定文件或目錄(大小寫不敏感)。
  • -o (outfile): 將輸出寫入指定文件,而不是標準輸出。
  • -s (syslog): 將輸出寫入系統日誌,而不是標準輸出。
  • --timefmt: 指定時間戳格式,配合 --format 使用。
  • --format: 自定義輸出格式,可以包括時間、事件類型、文件名等。
  • -e (event): 指定監控的事件類型(如 create、delete、modify 等)。

其中 timefmt 的時間格式 與 format 的格式如下

timefmt (時間格式使用 strftime 標準):

  • %Y:四位數的年份,例如:2023
  • %y:兩位數的年份,例如:23
  • %m:兩位數的月份(01-12)
  • %d:兩位數的日期(01-31)
  • %H:兩位數的小時(00-23)
  • %M:兩位數的分鐘(00-59)
  • %S:兩位數的秒數(00-60)

format :

  • %T:使用 timefmt 格式指定的時間戳
  • %w:監控的目錄名稱
  • %f:發生變化的文件名稱
  • %e:事件發生的類型(例如:IN_MODIFY、IN_DELETE 等)
  • %Xe:特定事件 e 的擴展格式,其中 X 是擴展選項

範例:
inotifywait -mr --timefmt "%Y-%m-%d %H:%M:%S" --format "%T%w%f event: %;e" /data/www

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

但是,並不是所有的事件觸發都需要同步,例如:查看文件 會觸發OPEN但這種事件不需要執行同步(或是說 不需要做任何對應的處理)

所以我們只需要關注以下這些事件即可:

  • create:當一個文件或目錄被創建時觸發。
  • delete:當一個文件或目錄被刪除時觸發。
  • moved_to:當一個文件或目錄被移動到監控的目錄中時觸發。
  • close_write:當一個打開用於寫入的文件被關閉時觸發。
  • attrib:當一個文件或目錄的屬性被修改時觸發。屬性包括權限、擁有者、時間戳等。

範例: inotifywait -mrq /data/www --timefmt "%F %H:%M:%S" --format "%T %W%f event: %;e" -e create,delete,moved_to,close_write,attrib

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

rsync 同步

如果想要機器上的資料備份到另一台機器 可以使用rsync
因為 rsync可以進行 增量複製

設置

機器1(左) 機器名稱 data (資料伺服器)
機器2(右) 機器名稱 backup (備份伺服器)
皆已使用ssh無密碼登入

目的是將 機器1 /data/www 的內容 備份到 機器2 /data/backup

[user@backup backup]$ rsync -ac data:/data/www/ .

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

但是目前存在一些問題
需要備份時都需要執行一次rsync命令 (使用contab)
但是刪除檔案的動作不會同步 需要加上 --delete 參數
可以使用crontab週期性更新 那要如何做到實時同步?
[優化] * * * * * rsync -ac --delete data:/data/www/ /data/backup &> /dev/null

使用排程(crond)設置每分鐘執行一次rsync命令
crontab -e輸入`* * * * * rsync -ac data:/data/www/ /data/backup

### 排程(crond)

yum install cronie

*: don’t care

分 時 日 月 周
1 * * * * 每小時的第1分鐘
*/1 * * * * 每1分鐘執行一次
*/2 * * * * 每2分鐘執行一次

1 * * * 每小時的第0分鐘
*/1 * * * 每1小時執行一次
/2: 代表每2時間(分、時、日…)執行一次

29 9 15 8 * (8/15 09:29 執行一次)
0 17 10 * * (每個月10日 下午5點整)
0 4 * * 6 (每個星期六 零晨4點整)
1,31 17 10 * * (每個17號 17點 1分、31分都執行一次)
1-10 17 10 * * (每個17號 17點 1分、2分…、10分都執行一次)

0 * * * * (每小時第0分鐘)

0 23-1/2,8 * * * 23,4,3,5,7,8

*/20 6-12 * 12 * 在12月時,6~12小時間 每20分鐘 執行一次

crontab -l: 列出当前用户的定时任务
crontab -r: 删除当前用户的所有定时任务。

rsync的運作模式

  1. 使用ssh存取
    用法類似 scp
    scp [參數] [來源] [目的]
    rsync [參數] [來源] [目的]
    ex:
    push:rsync /home/user/a.txt user@10.0.0.1:/home/user/a.txt
    pull: rsync user@10.0.0.1:/home/user/a.txt /home/user/a.txt

  2. 使用rsync獨立服務rsync-daemon(port 873/TCP)存取

rsync [參數] [來源] [目的]

ex:
push:
rsync /home/user/a.txt user@10.0.0.1::/home/user/a.txt
rsync /home/user/a.txt rsync://user@10.0.0.1:873 //home/user/a.txt
rsync /home/user/a.txt rsync://user@10.0.0.1 //home/user/a.txt

pull:
rsync user@10.0.0.1::/home/user/a.txt /home/user/a.txt
rsync rsync://user@10.0.0.1:873//home/user/a.txt /home/user/a.txt

wait4del

pull:
rsync [OPTION] [USER@]HOST::SRC [DST]
rsync [OPTION] rsync://[USER@]HOST[:POST]/SRC [DST]

push:
rsync [OPTION] SRC [USER@]HOST::DST
rsync [OPTION] SRC rsync://[USER@]HOST[:POST]/DST


image

rsync獨立服務

情境:
備份伺服器做rsync伺服器端
資料伺服器做rsync客戶端

設置rsync伺服器之前
只需要執行rsync --daemon就可以成為rsync伺服器端
但需要確保配置檔/etc/rsyncd.conf存在
image

rsync配置檔 設置

[共享名稱-自訂]
path=共享位置

範例

[backup]
path=/data/backup

配置檔寫好後 rsync客戶端 可以透過rsync rsync://HOST查看共享的位置

image
在配置檔設定後便會出現共享名稱
image
也可以使用另一種格式 或設置/etc/hosts


為了方便操作(使用systemctl)可以安裝rsync-daemon

yum install rsync-daemon
安裝套件同時也會建立配置檔/etc/rsyncd.conf與service文件
image
也可以設置成開機啟動systemctl enable --now rsyncd

但內部其其實也是使用rsync daemon
cat /usr/lib/systemd/system/rsyncd.service
image


但目前仍然無法存取,因為rsync需要設置共享系統的權限 與 文件系統的權限
image

前面的backup是HOST 後面的是共享名稱

需要在配置檔中加入read only = no,才能寫入

預設 read only是 yes
修改完要 重啟服務 systemctl restart rsyncd

接著需要設置文件系統的權限,否則報錯如下圖:

image

rsync預設是透過nobody用戶進行存取 所以需要讓rsync伺服器端設置對應權限

setfacl -m u:nobody:rwx /data/backup/

測試
rsync client(左): rsync /etc/passwd backup:backup
image
可以正常存取並且擁有者為nobody
如果以user的身分傳檔案rsync /etc/passed user@192.169.245.149::backup擁有者也會是nobody

但使用rsync-daemod傳輸資料時預設不需要驗證會有安全性的問題

使用ssh時會需要密碼或預先設置免密碼登入

所以需要啟用驗證功能 (在配置檔新增以下內容)

uid = root # 指定身份驗證通過時共享目錄,將之指定為生成的文件所有者,默認為nobody
gid = root # 提示身份驗證通過時,生成文件的group,默認為nobody
port = 873 # 指定啟動rsync服務時,監聽從哪個端口,默認為873/tcp
#use chroot = no # 默認為yes
max connections = 0
ignore errors
exclude = lost+found/
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
reverse lookup = no
#hosts allow = 10.0.0.0/24
[backup] # 每個模塊名對應一個不同的path目錄,如果同名後面模塊生效
path = /data/backup/
comment = backup dir
read only = no # 默認為yes,即只讀
auth users = rsyncuser # 默認為匿名用戶可以訪問rsync服務器
secrets file = /etc/rsync.pas

移除註解

uid = root 
gid = root 
port = 873 
max connections = 0
ignore errors
exclude = lost+found/
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
reverse lookup = no
[backup]
path = /data/backup/
comment = backup dir
read only = no
auth users = rsyncuser 
secrets file = /etc/rsync.pas

接著,將使用者與密碼user:password寫入到 /etc/rsync.pas
echo "rsyncuser:0000" > /etc/rsync.pas

為了提高安全性 可將存放密碼的檔案權限設置為600
chmod 600 /etc/rsync.pas

如此一來 登入時就會要求輸入密碼
但為了方便撰寫腳本,可以在client端設定一個密碼檔並以--password-file=密碼檔避免交互

image


[root@data-centos8 ~]# vim inotify_rsync.sh

#!/bin/bash
SRC='/data/www/' # 注意最後的/
DEST='rsyncuser@rsync服務器IP::backup'

rpm -q rsync &> /dev/null || yum -y install rsync
inotifywait -mrq --exclude=".*\.swp" --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %w %f' -e create,delete,moved_to,close_write,attrib ${SRC} | while read DATE TIME DIR FILE; do
    FILEPATH=${DIR}${FILE}
    rsync -az --delete --password-file=/etc/rsync.pas $SRC $DEST && echo "At ${TIME} on ${DATE}, file ${FILEPATH} was backed up via rsync" >> /var/log/changelist.log
done

執行腳本後

bash aa.sh

rsync server端執行watch -n0.1 ls -l /data/backup每0.1秒執行一次ls -l /data/backup

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →