最近看到這幾篇使用 inotify 做文件同步感到有興趣 雖然現在工作上目前還沒用到 但這種情境感覺很常遇到希望能用不用寫程式方法
相關工具
inotify-tools 監聽資料夾裡檔案異動工具 | 程式狂想筆記 之前小記這篇,其實裡面沒什麼實作 需透過 bash 執行 但這樣當然不是很方便,所以有類似 sersync 和 lsyncd 工具解決這個方案
這篇lsyncd实时同步搭建指南——取代rsync+inotify-Linux运维日志 有講到很多優點缺點備份圖 為了不浪費時間 所以我就不實作了
lsyncd 安裝 apt install rsyncd
或去 github 官網抓 axkibe/lsyncd: Lsyncd (Live Syncing Daemon) synchronizes local directories with remote targets
lua 記得要升到 5.2 Lua >= 5.2
Lsyncd depends on Lua 5.2 or greater; that is 5.2 or 5.3. For most distributions you need to install the liblua??, the liblua??-dev and the lua?? package, with ?? being the respective Lua version. cmake >= 2.8
To configure Lsyncd to your system, cmake >= 2.8 is required rsync >= 3.1
During runtime Lsyncd needs rsync > 3.1 installed both on source and target systems.
Lsyncd - Building
設定 一開始不會有/etc/lsyncd.conf
可以做 service lsync status
有沒有執行
vim /etc/lsyncd.conf 網路上看到是這個路徑 但是我看CONFIG=/etc/lsyncd/lsyncd.conf.lua
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 # 全域設定 settings { logfile = "/var/log/lsyncd/lsyncd.log", statusFile = "/var/log/lsyncd/lsyncd.status" inotifyMode = "CloseWrite", maxProcesses = 8, } ## 以下設定參考 https://www.centos.bz/2017/08/lsyncd-rsync-inotify/ # 可設定多組 # I. 本地目錄同步,direct:cp/rm/mv。 適用:500+萬文件,變動不大 sync { default.direct, source = "/tmp/src", target = "/tmp/dest", delay = 1 maxProcesses = 1 } # II. 本地目錄同步,rsync模式:rsync sync { default.rsync, source = "/tmp/src", target = "/tmp/dest1", excludeFrom = "/etc/rsyncd.d/rsync_exclude.lst", rsync = { binary = "/usr/bin/rsync", archive = true, compress = true, bwlimit = 2000 } } # III. 遠程目錄同步,rsync模式 + rsyncd daemon sync { default.rsync, source = "/tmp/src", target = "syncuser@172.29.88.223::module1", delete="running", # 可以改成false 這樣就不會刪掉 exclude = { ".*", ".tmp" }, delay = 30, init = false, # 默認init功能設置為false來跳過初始rsync過程 rsync = { binary = "/usr/bin/rsync", archive = true, compress = true, verbose = true, password_file = "/etc/rsyncd.d/rsync.pwd", _extra = {"--bwlimit=200"} } } # IV. 遠程目錄同步,rsync模式 + ssh shell sync { default.rsync, source = "/tmp/src", target = "172.29.88.223:/tmp/dest", # target = "root@172.29.88.223:/remote/dest", # 上面target,注意如果是普通用戶,必須擁有寫權限 maxDelays = 5, delay = 30, # init = true, rsync = { binary = "/usr/bin/rsync", archive = true, compress = true, bwlimit = 2000 # rsh = "/usr/bin/ssh -p 22 -o StrictHostKeyChecking=no" # 如果要指定其它端口,請用上面的rsh } } # V. 遠程目錄同步,rsync模式 + rsyncssh,效果與上面相同 sync { default.rsyncssh, source = "/tmp/src2", host = "172.29.88.223", targetdir = "/remote/dir", excludeFrom = "/etc/rsyncd.d/rsync_exclude.lst", # maxDelays = 5, delay = 0, # init = false, rsync = { binary = "/usr/bin/rsync", archive = true, compress = true, verbose = true, _extra = {"--bwlimit=2000"}, }, ssh = { port = 1234 } }
default.direct
Default.direct可以用來保持兩個本地目錄同步,比使用default.rsync更好的性能。Default.direct在啟動時使用(就像default.rsync一樣)rsync來初始化目標目錄與源目錄的同步。但是,在正常操作期間,default.direct使用/ bin / cp,/ bin / rm和/ bin / mv來保持同步。所有參數就像default.rsync一樣。
delete 也適用這個屬性
_extra 可放一些參數
想說有沒有 size-only 設定 但發現都找不到 後來看到_extra
可以設定
簡單測試 預設是 10 秒檢查資料更新 可設定 statusIntervalLsyncd - The Configuration File
1 2 3 4 5 6 7 8 9 10 settings { logfile = "/tmp/lsyncd.log" , statusFile = "/tmp/lsyncd.status" , nodaemon = true , } sync { default.rsync, source = "/home/malagege/test_lsyncd/a/" , target = "/home/malagege/test_lsyncd/b/" ,
default.rsync 預設是執行 /usr/bin/rsync -ltsd –delete –include-from=- –exclude=* SOURCE TARGET 所以會做刪除動作
同步完做動作 Lsyncd - FAQ: How can I call a script before or after each rsync operation?
1 2 3 4 5 6 7 8 9 10 #!/bin/bash /usr/bin/rsync "$@ " result=$? ( if [ $result -eq 0 ]; then echo "my commands" ; fi ) >/dev/null 2>/dev/null </dev/null exit $result
這邊注意 rsync 並不是對單一檔案做搬移 而是對整個… echo $@ 結果是-slt -r --delete --ignore-errors --force --from0 --include-from=- --exclude=* /home/malagege/test_lsyncd/a/ /home/malagege/test_lsyncd/a/ /home/malagege/test_lsyncd/b/
跟我想要抓的東西不一樣
可能做 Layer 2 做自訂動作 感覺這邊自由度很高 因為我對 lua 不熟 所以就沒打算做這段
其他參考
同步腳本 以下都是參考:真正的inotify+rsync实时同步 彻底告别同步慢 - 琴酒网络 - 博客园
1 2 3 4 5 6 #!/bin/bash /usr/bin/inotifywait -mrq --format '%w%f' -e create,close_write,delete /backup |while read file do cd /backup && rsync -az --delete /backup/ rsync_backup@192.168.24.101::backup/--password-file=/etc/rsync.password done
優化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #!/bin/bash src=/data/ des=data rsync_passwd_file=/etc/rsyncd.passwd ip1=192.168.0.18 ip2=192.168.0.19 user=root cd ${src} /usr/local /bin/inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib,close_write,move ./ | while read file do INO_EVENT=$(echo $file | awk '{print $1}' ) INO_FILE=$(echo $file | awk '{print $2}' ) echo "-------------------------------$(date) ------------------------------------" echo $file if [[ $INO_EVENT =~ 'CREATE' ]] || [[ $INO_EVENT =~ 'MODIFY' ]] || [[ $INO_EVENT =~ 'CLOSE_WRITE' ]] || [[ $INO_EVENT =~ 'MOVED_TO' ]] then echo 'CREATE or MODIFY or CLOSE_WRITE or MOVED_TO' rsync -avzcR --password-file=${rsync_passwd_file} $(dirname ${INO_FILE} ) ${user} @${ip1} ::${des} && rsync -avzcR --password-file=${rsync_passwd_file} $(dirname ${INO_FILE} ) ${user} @${ip2} ::${des} fi if [[ $INO_EVENT =~ 'DELETE' ]] || [[ $INO_EVENT =~ 'MOVED_FROM' ]] then echo 'DELETE or MOVED_FROM' rsync -avzR --delete --password-file=${rsync_passwd_file} $(dirname ${INO_FILE} ) ${user} @${ip1} ::${des} && rsync -avzR --delete --password-file=${rsync_passwd_file} $(dirname ${INO_FILE} ) ${user} @${ip2} ::${des} fi if [[ $INO_EVENT =~ 'ATTRIB' ]] then echo 'ATTRIB' if [ ! -d "$INO_FILE " ] then rsync -avzcR --password-file=${rsync_passwd_file} $(dirname ${INO_FILE} ) ${user} @${ip1} ::${des} && rsync -avzcR --password-file=${rsync_passwd_file} $(dirname ${INO_FILE} ) ${user} @${ip2} ::${des} fi fi done
簡單來看就是對檔案做 dirname 備份,減少做多次遞迴 是不是能確認來源是資料夾或檔案,單純 scp 或 rsync 過去是不是比較快?
相關同步數量問題 以下參考:等很久資訊室: Lsyncd - Live syncing Daemon 資料夾同步
檢查可監測數量設定值: lsyncd 是依靠 kernel 內建的檔案監測功能 inotify,來回報記錄檔案狀態,而 inotify 預設有設定了一個可監測資料夾數量的限定值。
cat /proc/sys/fs/inotify/max_user_watches
在 CentOS 6.8 內,它預設值是 8192,也就是它只能監測最多 8192 個資料夾。 而我們要同步的資料夾有多少,會不會超過這個數值呢?必竟,若是超過了,它就無法同步到了。
cat /var/run/lsyncd/lsyncd.status
在狀態檔中找到一行如下: Inotify watching 1440 directories 那數字便是目前 lsyncd 所監測的資料夾數量。 如果您看到的數字很靠近 8192 或甚至超過,那就必須放大這個限定值。
echo ‘10000’ > /proc/sys/fs/inotify/max_user_watches
這樣可以即時把限定值改成 10000,但重開機後它又會變成原本的 8192。 下面方法可以改變開機後的預設值:
把上述即時修改的指令放到 rc.local 之類的開機啟動檔內。 或是 在 /etc/sysctl.conf 內加上一行 fs.inotify.max_user_watches = 10000
這樣它重開機後,一樣會放大成我們設定的數值。