Linux rsync 企業級應用
簡介
rsync 是 Linux 下的資料同步工具, 其支援本地同步和遠端同步, 遠端同步分為 daemon 和 ssh 同步方式
rsync 可以代替 cp, scp 等命令, 且具有更高的可靠性
優點:
1、同步時能夠完整的保留資料目錄結構、許可權、時間、軟硬連結等
2、能夠實現增量同步, 每一次同步只會同步發生過改變的資料
3、檔案傳輸效率高
4、支援匿名傳輸
5、無須特殊許可權即可安裝
6、支援流控制, 可以精確同步速度和使用的頻寬大小
rsync 常用命令
-v, --verbose 輸出詳細的資料同步過程 --version 檢視版本資訊 -q, --quiet 靜默模式 -c, --checksum 對傳輸的資料進行校驗和檢查, 預設情況下 rsync 進行快速檢查, 使用基於校驗和的檢查意味著會大量的消耗磁碟 IO 降低傳輸速度 -a, --archive 歸檔模式, 等於 -rlptgoD -d --dirs 以不遞迴的方式拷貝目錄本身。遞迴時, 如果源為 "dir1/file1", 則不會拷貝 dir1 目錄, 使用該選項將拷貝 dir1 但不拷貝 file1 -P, --partial 保留那些因故沒有完全傳輸的檔案, 以加快隨後的再次傳輸 -r, --recursive 遞迴複製目錄 -R --relative 使用相對路徑, 這意味著將命令列中指定的全路徑而非路徑最尾部的檔名傳送給服務端 -b, --backup 建立備份, rsync 將在每個檔案被傳輸或刪除時重新命名(filename~) 先前存在的目標檔案 --backup-dir=DIR 使用 -b 建立備份時, 可以使用 --backup-dir 將檔案備份到指定的目錄中 --suffix=SUFFIX 使用 -b 建立備份時, 可以使用 --suffix 指定備份檔案的字尾(預設為 filename~) -u, --update 僅在源 mtime 比目標已存在檔案的mtime新時才拷貝, 注意: 該選項是接收端判斷的, 不會影響刪除行為 -l, --links 遇到符號連結時, 在目標上重新建立符號連結 -L, --copy-links 遇到符號連結時, 拷貝符號連結指向的原檔案 --safe-links 忽略指向複製樹之外的所有符號連結 -k, --copy-dirlinks 如果符號連結為一個目錄, 則進行 --copy-links 操作, 如果您不希望非目錄的符號連結受到影響, 這是非常有用的 -H, --hard-links 保持硬連結 -p, --perms 保持檔案許可權 -A, --acls 保持檔案的 acl, 原系統和目標系統的 ACL 相容才能工作 -o, --owner 保持檔案的屬主, 僅當接收到的 rsync 作為超級使用者執行時才能工作, 預設許可權為接受端使用者的許可權 -g, --group 保持檔案的屬組, 僅當接收到的 rsync 作為超級使用者執行時才能工作 -D, --devices 保持裝置檔案資訊, 僅當接收到的 rsync 作為超級使用者執行時才能工作 -t, --times 保持檔案修改時間 -O, --omit-dir-times 保持檔案修改時間時忽略目錄, 如果在接收端使用 NFS 共享目錄, 則最好使用 -O 選項 -J, --omit-link-times 保持檔案修改時間時忽略符號連結 --super 告訴接受方嘗試以超級使用者執行 rsync, 如果是超級使用者可以使用 --no-super 關閉以超級使用者身份執行 --fake-super 通過嘗試新增特殊許可權來模擬超級使用者執行 -S, --sparse 對稀疏檔案進行特殊處理以節省 DST 的空間 -n, --dry-run 測試執行, 檢視將有哪些資料被傳輸 -W, --whole-file 禁用增量檢測, rsync 將使用全量傳輸, 在網路頻寬高於磁碟頻寬時, 該選項比增量傳輸更高效 -x, --one-file-system 禁止跨越檔案系統(當遇到符號連結時, 如果符號連結為一個目錄, 則 rsync 將其當成一個掛載點忽略; 如果符號連結為檔案則不受此選項影響) --existing 僅更新目標端已存在的檔案, 跳過 DST 上不存在的檔案或目錄, 該選項和 --ignore-existing 一起使用時將不會更新任何的檔案(在使用 --delete 時肯會有用, 這將刪除 DST 上多餘的檔案) --ignore-non-existing 和 --existing 相同 --ignore-existing 僅更新目標端不存在的檔案, 跳過 DST 上已存在的檔案或目錄 delete 操作: --delete 刪除 DST 上 SRC 不存在的資料 # 下面 4 個選項都隱含了 delete 操作 --delete-before 在傳輸檔案之前先執行 delete 操作(這在 DST 磁碟空間比較緊缺時是比較有效的), 如果指定了傳輸超時時間該選項可能會造成傳輸超時 該選項強制 rsync 使用舊的非增量的遞迴演算法, 該演算法要求 rsync 掃描傳輸中的所有檔案 --delete-during, --del --delete 在大多數情況下采用的演算法 ,請求在傳輸發生時增量地刪除接收端上的檔案, 每個目錄的刪除掃描是在每個目錄檢查更新之前完成的, 相對於 --delete-before 更高效 --delete-after 請求在傳輸完成後刪除接收端上的檔案, 該選項強制 rsync 使用舊的非增量的遞迴演算法, 該演算法要求 rsync 掃描傳輸中的所有檔案 --delete-delay 請求在傳輸過程中計算接收端上的檔案刪除, 然後在傳輸完成後刪除 這在與 --delay-updates and/or --fuzzy 使用時非常用於, 比 --delete-after 更有效 --ignore-errors 及時出現 IO 錯誤也進行 delete 操作 --remove-source-files 刪除源端檔案, 當 rsync 將源端的檔案拷貝到 DST 時, rsync 將會刪除源端的檔案, 沒有拷貝或者拷貝失敗的檔案不會被刪除 --size-only rsync 僅檢查檔案大小, 預設情況下 rsync 會檢查檔案大小和 mtime --force 當要使用非目錄替換一個非空目錄時, 刪除非空目錄(刪除目錄, 即使目錄不為空) --max-delete=NUM 指定刪除檔案或目錄的最大數量 --max-size=SIZE 指定傳輸檔案的最大大小, 單位K, M, G --min-size=SIZE 指定傳輸檔案的最小大小, 單位K, M, G -f, --filter=RULE 使用指定規則篩選不需要傳輸的資料, 示例: rsync -r --filter='exclude *.log' /var/log/ /mnt/ RULE: 1、exclude 規則: 即排除規則, 只作用於傳送端, 被排除的檔案不會進入檔案列表 2、include 規則: 即包含規則, 只作用於傳送端, 被包含的檔案將明確記錄到檔案列表中 3、hide 規則: 即隱藏規則, 只作用於傳送端, 隱藏後的檔案對於接收端來說是看不見的, 也就是說接收端會認為它不存在於源端 4、show 規則: 即顯示規則, 只作用於傳送端, 是隱藏規則的反向規則 5、protect 規則: 即保護規則, 該規則只作用於接收端, 被保護的檔案不會被刪除掉 6、risk 規則: 即取消保護規則, 是protect的反向規則 7、clear 規則: 刪除i nclude/exclude 規則列表 --exclude=PATTERN --filter 的簡寫模式, 指定排除不需要傳輸的檔案模式 --include=PATTERN --filter 的簡寫模式, 指定不排除而需要傳輸的檔案模式 -z, --compress 傳輸資料時啟用壓縮, 這個操作會用到大量的cpu資源, 但是可以節約頻寬 --compress-level=NUM 壓縮級別 --skip-compress=LIST 不壓縮的檔案列表(已經壓縮過的檔案通常不需要再壓縮), 示例: --skip-compress=gz/jpg/7z/bz2 (不壓縮 gz, jpg, 7z, bz2) 等型別的檔案 --bwlimit=RATE 指定傳輸速率, 單位秒(s), 示例: --bwlimit=10m --timeout=TIMEOUT 設定 I/O 超時時間, 如果在這段時間之內沒有傳輸資料則 rsync 退出, 單位秒(s), 預設值為 0, 表示永不超時 --contimeout 設定與 rsync daemon 連線超時的時間 --log-file 指定日誌檔案 --log-file-format 設定日誌格式 --stats 輸出傳輸過程中的詳細資訊 --iconv=CONVERT_SPEC 指定傳輸編碼, 預設 utf8 --no-OPTION 在選項見面加一個 --no 表示關閉這個選項(rsync 有一些預設選項, 可以使用這個引數來關閉它), 注意: 不是所有選項都可以關閉 # 作為 daemon 執行的引數 --daemon 將 rsync 作為守護程序執行 --address rsync daemon 監聽的地址 --port rsync daemon 監聽的埠 --sockopts 監聽的 unix 套接字地址 --password-file=FILE 從指定檔案獲取 rsync daemon 的使用者名稱和密碼 -4, --ipv4 監聽 ipv4 地址 -6, --ipv6 監聽 ipv6 地址 --config 指定配置檔案 --bwlimit=RATE 設定傳輸速率
本地檔案系統之間的同步
# 將 /etc 同步到 /mnt/, 注意: 如果 etc 結尾加上 / 將同步 etc 目錄下的所有檔案單不會同步 etc 這個目錄 rsync -a /etc /mnt/ # 將 /etc/yum.repos.d 拷貝到 /mnt, 目錄結構為 /mnt/yum.repos.d/ rsync -r /etc/yum.repos.d /mnt # 將 /etc/yum.repos.d 拷貝到 /mnt, 但是在 yum.repos.d 上面生成 etc 目錄, 目錄結構為 /mnt/etc/yum.repos.d/ rsync -Rr /etc/yum.repos.d /mnt # 對長目錄進行劃分, 以 . 表示相對目錄的起點, 目錄結構為 /mnt/system/reboot.target.wants/ rsync -Rr /usr/lib/systemd/./system/reboot.target.wants/ /mnt/ # 將 /var/log 目錄下除以 .log 結尾的檔案和目錄結尾的資料同步到 /mnt rsync -a --exclude='*.log' /var/log /mnt/ # 刪除 /var/log/ 所有以 .log 結尾的檔案 rsync -a --delete /mnt/log/ /var/log/ # 以每秒 1k 的速度同步 rsync -av --bwlimit=1k /etc/yum.repos.d/ /mnt/ # 檔案大小在 10M 以下的檔案不進行同步 rsync -av --min-size=10M /var /mnt/ # 複製符號連結的原始檔案 rsync -avL /bin /mnt # 對舊的檔案進行備份, 當檔案同步時接收端會重新命名已存在的檔案, 在和原始檔同一個目錄中生成 filename~ 的備份檔案 rsync -aP --backup /etc /mnt/ # 將備份的檔案放入 /opt/ 中, 指定了 --backup-dir 選項之後, 在備份目錄將不會對檔案生成字尾 rsync -aP --backup --backup-dir=/opt/ /etc /mnt/ # 對備份檔案生成自定義字尾 rsync -aP --backup --backup-dir=/opt/ --suffix=".$(date +'%Y-%m-%d_%H:%M:%S')" /etc /mnt/
遠端同步環境配置
# 安裝 rsync 命令(客戶端和伺服器端都需要安裝) yum -y install rsync # 關閉 firewalld 和 selinux systemctl disbale firewalld systemctl stop firewalld setenforce 0
基於 SSH 的遠端同步
# 使用 ssh 方式同步, 如果配置了祕鑰登入則 rsync 直接將資料拷貝到目標主機, 如果沒有設定祕鑰登入, rsync 會詢問使用者密碼 rsync /etc [email protected]:/tmp/ # 指定 ssh 的引數 rsync -aP /etc -e 'ssh -p 22' [email protected]:/tmp/ # 第一次 ssh 連線時, 直接將主機資訊加入到 known_hosts 檔案 rsync -aP /etc -e 'ssh -o StrictHostKeyChecking=no' [email protected]:/tmp/
基於 daemon 的遠端同步
rsync daemon 能夠接收客戶端的推送和下載請求
客戶端可以將修改過的內容推送到 rsync daemon 以供其他的客戶端進行更新
使用 rsync --daemon 啟動 rsync 的 daemon 模式, rsync daemon 預設會讀取 /etc/rsyncd.conf 作為其配置檔案
centos 7 rsync 的預設配置
cat /etc/rsyncd.conf # /etc/rsyncd: configuration file for rsync daemon mode # See rsyncd.conf man page for more options. # configuration example: # uid = nobody # gid = nobody # use chroot = yes # max connections = 4 # pid file = /var/run/rsyncd.pid # exclude = lost+found/ # transfer logging = yes # timeout = 900 # ignore nonreadable = yes # dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2 # [ftp] # path = /home/ftp # comment = ftp export area
編寫 /etc/rsyncd.conf
################################## 定義全域性配置 ################################## # 監聽 socket 地址 port = 873 address = 0.0.0.0 # 執行 rsync daemon 的使用者和使用者組 uid = nobody gid = nobody # 是否限制在指定目錄 use chroot = yes # 客戶端是否只讀 # 在 centos 6 中該引數的值為 yes 或者 no # read only = false # 拒絕和執行訪問的主機 hosts deny = * hosts allow = 192.168.1.0/24 # 最大連線數 max connections = 50 # 連線超時時間 timeout = 300 # 是否列出所有模組 list = true # 認證使用者 auth users = nobody # 認證檔案, 格式為: username:password , 認證檔案的許可權必須為 600 secrets file = /etc/rsyncd/rsyncd.secrets # 客戶端連線過來顯示的訊息 motd file = /etc/rsyncd/rsyncd.motd # 鎖檔案 lock file = /var/run/rsync.lock # 日誌檔案和 pid 檔案 log file = /var/log/rsyncd.log pid file = /var/run/rsyncd.pid # 對以下檔案型別不進行壓縮 dont compress = *.7z *.ace *.avi *.bz2 *.deb *.gpg *.gz *.iso *.jpeg *.jpg *.lz *.lzma *.lzo *.mov *.ogg *.png *.rar *.rpm *.rzip *.tbz *.tgz *.tlz *.txz *.xz *.zip ################################## 定義模組配置, 模組配置可以存在多個, 模組配置可以覆蓋全域性配置(有的全域性配置不能被覆蓋, 比如: address 和 port) ################################## # 模組 ID, 全域性唯一 [htdocs] # 模組路徑, 該引數必須指定 path = /usr/local/httpd/htdocs # 忽略一些 IO 錯誤資訊 ignore errors # 是否只讀(不能上傳) read only = false # 是否只寫(不能下載) write only = false # 排除 test 目錄 exclude = test # 描述資訊, 客戶端使用 --list-only 檢視 comment = 'web page file'
測試和啟動:
mkdir -p /usr/local/httpd/htdocs # 建立幾個測試目錄 mkdir /usr/local/httpd/htdocs/{html,php,jpg,test} # 建立測試檔案 echo '<h1>Hello Rsync</h1>' > /usr/local/httpd/htdocs/html/index.html echo '<?php echo "Hello Rsync"?>' > /usr/local/httpd/htdocs/php/index.php echo 'test' > /usr/local/httpd/htdocs/test/test.txt # 更改 rsync 模組目錄許可權 chown -R nobody:nobody /usr/local/httpd/htdocs # 建立使用者認證檔案 mkdir /etc/rsyncd/ echo "nobody:123" >> /etc/rsyncd/rsyncd.secrets chmod 600 /etc/rsyncd/rsyncd.secrets # 設定客戶端連線過來顯示的訊息 echo "Hello Rsync" > /etc/rsyncd/rsyncd.motd # 啟動 rsync daemon (centos 7 使用 systemd 啟動, centos 6 使用 rsync --daemon 啟動) systemctl start rsyncd
客戶端操作
# rsync daemon 和客戶端之間的通訊和傳輸使用的是 ssh 協議 # 請求列出伺服器端的所有模組資訊(伺服器端會要求輸入密碼), 埠預設為 873, 所有可以省略 rsync --list-only --port 873 [email protected]:: # 建立客戶端認證檔案 echo "123" > /tmp/rsync_secrets chmod 600 /tmp/rsync_secrets # 檢視 htdocs 模組的詳細資訊, 使用 --password-file 指定認證檔案, rsync 認證是會自動讀取該檔案的內容作為認證密碼 rsync --list-only [email protected]::htdocs --password-file=/tmp/rsync_secrets # 將伺服器端的 htdocs 模組的內容下載到 /mnt/ 目錄, test 目錄不會被下載 rsync -aP [email protected]::htdocs --password-file=/tmp/rsync_secrets /mnt/ # 客戶端推送資料到伺服器端(使用方法和 scp 類似) rsync -aP /tmp/ [email protected]::htdocs --password-file=/tmp/rsync_secrets
rsync + sersync 實現實時同步
rsync daemon 實現了一個客戶端的更新, 其他的客戶端也能獲取的功能, 但是其他客戶端什麼時候去向伺服器獲取最新的內容那 ?
寫一個計劃任務每一分鐘詢問一次, 在檔案數量少的情況下還可行, 但是如果檔案數量比較多那麼 rsync 每一次去掃描都需要大量的時間和系統資源, 在檔案數量大的情況下得不償失。
這時我們可以通過監聽目錄的檔案狀態來獲取那些檔案傳送了改變, 將這些發生了改變的檔案推送到所有的客戶端。在 Linux 中實現這個功能的是 Linux kernel 的一個特性叫做 Inotify
sersync:
Inotify 是 Linux kernel 2.6.13 以上提供的特性, 它監控檔案系統操作, 比如讀取、寫入和建立
sersync 是基於 inotify 開發的, 可以記錄下被監聽目錄中發生變化的(包括增加、刪除、修改)具體某一個檔案或者某一個目錄的名字
使用 rsync 同步的時, 只同步發生變化的檔案或者目錄, 因此效率更高。類似功能的還有 inotify-tools
sersync 的優點:
1、sersync 採用多執行緒進行同步(預設開啟 10 個執行緒), 能夠同時處理多個 Inotify 事件
2、sersync 異常處理機制, 通過失敗佇列自動對之前發生異常的檔案進行重新同步操作, 如果依舊失敗, 每 10 個小時會對同步失敗的檔案再次進行同步操作, 直到檔案同步為止
3、sersync 自帶 crond 功能, 無需藉助系統的 crond
實驗環境:
實驗需求: 一臺機器的檔案發生變化將發生變化的檔案推送到所有的 rsync daemon 上 IP 地址 角色 192.168.1.99 rsync daemon 192.168.1.100 rsync daemon 192.168.1.101 rsync client, sersync 所有的 rsync daemon 配置如上
安裝 sersync(192.168.1.101):
# sersync 託管在 google code 上, 在國內需要科學上網才能下載, 但是國內有人將 sersync 放在 GitHub 上了(可能不是最新的), 測試時可以從 GitHub 下載 # sersync 最新的下載地址 https://code.google.com/archive/p/sersync/downloads wget https://raw.githubusercontent.com/wsgzao/sersync/master/sersync2.5.4_64bit_binary_stable_final.tar.gz tar xvf sersync2.5.4_64bit_binary_stable_final.tar.gz cd /root/GNU-Linux-x86
編寫 sersync 配置檔案:
<?xml version="1.0" encoding="ISO-8859-1"?> <head version="2.5"> <!--本地socket--> <host hostip="localhost" port="8008"></host> <!--是否啟用 debug 模式--> <debug start="false"/> <!--是否啟用xfs檔案系統--> <fileSystem xfs="false"/> <!--同步時忽略推送的檔案(正則表示式), 預設關閉 --> <filter start="false"> <exclude expression="(.*)\.svn"></exclude> <exclude expression="(.*)\.gz"></exclude> <exclude expression="^info/*"></exclude> <exclude expression="^static/*"></exclude> </filter> <!--設定 Inotify 監聽的事件型別--> <inotify> <delete start="true"/> <createFolder start="true"/> <createFile start="false"/> <closeWrite start="true"/> <moveFrom start="true"/> <moveTo start="true"/> <attrib start="false"/> <modify start="false"/> </inotify> <sersync> <!-- watch: Inotify 事件監聽的目錄 --> <localpath watch="/backup"> <!-- ip: rsync daemon 地址, name: 客戶端需要同步的 rsync 模組--> <remote ip="192.168.1.99" name="htdocs"/> <remote ip="192.168.1.100" name="htdocs"/> </localpath> <rsync> <!--rsync 命令引數--> <commonParams params="-artuz"/> <!--start: true 啟用密碼檔案認證 users: rsync 認證使用者 passwordfile: 密碼認證檔案--> <auth start="true" users="nobody" passwordfile="/etc/rsyncd_auth.pass"/> <!--port: rsync 監聽的埠--> <userDefinedPort start="false" port="874"/> <!-- 連線超時時間 --> <timeout start="false" time="300"/> <ssh start="false"/> </rsync> <!-- sersync 傳輸失敗日誌指令碼路徑, 每隔 60m 會重新執行該指令碼, 執行完畢會自動清空 --> <failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/> <!--sersync 計劃任務, 預設關閉--> <crontab start="false" schedule="600"> <crontabfilter start="false"> <exclude expression="*.php"></exclude> <exclude expression="info/*"></exclude> </crontabfilter> </crontab> <!--sersync 傳輸後呼叫 name 指定的外掛指令碼, 預設關閉--> <plugin start="false" name="command"/> </sersync> <!-- 外掛示例 <plugin name="command"> <param prefix="/bin/sh" suffix="" ignoreError="true"/> <filter start="false"> <include expression="(.*)\.php"/> <include expression="(.*)\.sh"/> </filter> </plugin> <plugin name="socket"> <localpath watch="/opt/tongbu"> <deshost ip="192.168.138.20" port="8009"/> </localpath> </plugin> <plugin name="refreshCDN"> <localpath watch="/data0/htdocs/cms.xoyo.com/site/"> <cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/> <sendurl base="http://pic.xoyo.com/cms"/> <regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/> </localpath> </plugin> --> </head>
啟動:
# 設定配置檔案許可權 chmod 644 confxml.xml # 建立認證檔案 echo "123" > /etc/rsyncd_auth.pass chmod 600 /etc/rsyncd_auth.pass # 建立監聽目錄 mkdir /backup # 啟動 ./sersync2 -r -d -o confxml.xml
測試:
192.168.1.101: echo "123" > /backup/123.txt 192.168.1.99 和 192.168.1.100 ls /usr/local/httpd/htdocs/