rsync簡介
rsync是linux系統下的數據鏡像備份工具。使用快速增量備份工具Remote Sync可以遠程同步,支持本地復制,或者與其他SSH、rsync主機同步。
rsync特性
rsync支持很多特性:
- 可以鏡像保存整個目錄樹和文件系統
- 可以很容易做到保持原來文件的權限、時間、軟硬鏈接等等
- 無須特殊權限即可安裝
- 快速:第一次同步時rsync會復制全部內容,但在下一次只傳輸修改過的文件。rsync在傳輸數據的過程中可以實行壓縮及解壓縮操作,因此可以使用更少的帶寬
- 安全:可以使用scp、ssh等方式來傳輸文件,當然也可以通過直接的socket連接
- 支持匿名傳輸,以方便進行網站鏡像
rsync的ssh認證協議
rsync命令來同步系統文件之前要先登錄remote主機認證,認證過程中用到的協議有2種:
- ssh協議
- rsync協議
rsync server端不用啟動rsync的daemon進程,只要獲取remote host的用戶名和密碼就可以直接rsync同步文件
rsync server端因為不用啟動daemon進程,所以也不用配置文件/etc/rsyncd.conf
ssh認證協議跟scp的原理是一樣的,如果在同步過程中不想輸入密碼就用ssh-keygen -t rsa打通通道
//這種方式默認是省略了 -e ssh 的,與下面等價: rsync -avz /SRC -e ssh root@192.168.100.132:/DEST -a //文件宿主變化,時間戳不變 -V //顯示詳細信息的過程 -z //壓縮數據傳輸 //當遇到要修改端口的時候,我們可以: #修改了ssh 協議的端口,默認是22 rsync -avz /SRC -e "ssh -p2222" root@192.168.100.133:/DEST
rsync命令
-v, --verbose 詳細模式輸出 -q, --quiet 精簡輸出模式 -c, --checksum 打開校驗開關,強制對文件傳輸進行校驗 -a, --archive 歸檔模式,表示以遞歸方式傳輸文件,並保持所有文件屬性,等於-rlptgoD -r, --recursive 對子目錄以遞歸模式處理 -R, --relative 使用相對路徑信息 -b, --backup 創建備份,也就是對於目的已經存在有同樣的文件名時,將老的文件重新命名為~filename。可以使用--suffix選項來指定不同的備份文件前綴。 --backup-dir 將備份文件(如~filename)存放在在目錄下。 -suffix=SUFFIX 定義備份文件前綴 -u, --update 僅僅進行更新,也就是跳過所有已經存在於DST,並且文件時間晚於要備份的文件。(不覆蓋更新的文件) -l, --links 保留軟鏈結 -L, --copy-links 像對待常規文件一樣處理軟鏈接 --copy-unsafe-links 僅僅拷貝指向SRC路徑目錄樹以外的鏈接 --safe-links 忽略指向SRC路徑目錄樹以外的鏈接 -H, --hard-links 保留硬鏈接 -p, --perms 保持文件權限 -o, --owner 保持文件屬主信息 -g, --group 保持文件屬組信息 -D, --devices 保持設備文件信息 -t, --times 保持文件時間信息 -S, --sparse 對稀疏文件進行特殊處理以節省DST的空間 -n, --dry-run 顯示哪些文件將被傳輸 -W, --whole-file 拷貝文件,不進行增量檢測 -x, --one-file-system 不要跨越文件系統邊界 -B, --block-size=SIZE 檢驗算法使用的塊尺寸,默認是700字節 -e, --rsh=COMMAND 指定使用rsh、ssh方式進行數據同步 --rsync-path=PATH 指定遠程服務器上的rsync命令所在路徑信息 -C, --cvs-exclude 使用和CVS一樣的方法自動忽略文件,用來排除那些不希望傳輸的文件 --existing 僅僅更新那些已經存在於DST的文件,而不備份那些新創建的文件 --delete 刪除那些DST中SRC沒有的文件 --delete-excluded 同樣刪除接收端那些被該選項指定排除的文件 --delete-after 傳輸結束以后再刪除 --ignore-errors 即使出現IO錯誤也進行刪除 --max-delete=NUM 最多刪除NUM個文件 --partial 保留那些因故沒有完全傳輸的文件,以是加快隨后的再次傳輸 --force 強制刪除目錄,即使不為空 --numeric-ids 不將數字的用戶和組ID匹配為用戶名和組名 --timeout=TIME IP超時時間,單位為秒 -I, --ignore-times 不跳過那些有同樣的時間和長度的文件 --size-only 當決定是否要備份文件時,僅僅察看文件大小而不考慮文件時間 --modify-window=NUM 決定文件是否時間相同時使用的時間戳窗口,默認為0 -T --temp-dir=DIR 在DIR中創建臨時文件 --compare-dest=DIR 同樣比較DIR中的文件來決定是否需要備份 -P 等同於 --partial --progress 顯示備份過程 -z, --compress 對備份的文件在傳輸時進行壓縮處理 --exclude=PATTERN 指定排除不需要傳輸的文件模式 --include=PATTERN 指定不排除而需要傳輸的文件模式 --exclude-from=FILE 排除FILE中指定模式的文件 --include-from=FILE 不排除FILE指定模式匹配的文件 --version 打印版本信息 --address 綁定到特定的地址 --config=FILE 指定其他的配置文件,不使用默認的rsyncd.conf文件 --port=PORT 指定其他的rsync服務端口 --blocking-io 對遠程shell使用阻塞IO -stats 給出某些文件的傳輸狀態 --progress 在傳輸時顯示傳輸過程 --log-format=formAT 指定日志文件格式 --password-file=FILE 從FILE中得到密碼 --bwlimit=KBPS 限制I/O帶寬,KBytes per second -h, --help 顯示幫助信息
實現rsync自動同步
環境
| 主機名 | IP地址 | 安裝的應用 | 系統版本 |
|---|---|---|---|
| RS1 | 192.168.100.132 | rsync | redhat8 |
| RS2 | 192.168.100.133 | rsync | redhat8 |
准備工作
//RS1 //安裝rsync yum -y install rsync //關閉防火牆,selinux systemctl stop firewalld setenforce 0 //RS2 //安裝rsync yum -y install rsync //關閉防火牆,selinux systemctl stop firewalld setenforce 0
ssh協議本地同步
//本地同步一個文件 [root@RS1 ~]# ls anaconda-ks.cfg [root@RS1 ~]# echo test >abc [root@RS1 ~]# ls abc anaconda-ks.cfg [root@RS1 ~]# mkdir /opt/abcd [root@RS1 ~]# rsync -avz abc /opt/abcd sending incremental file list abc sent 91 bytes received 35 bytes 252.00 bytes/sec total size is 5 speedup is 0.04 [root@RS1 ~]# cat /opt/abcd/abc test
//同步一個目錄 創建一個與下面tree顯示相同的結構 [root@RS1 ~]# tree test/ test/ ├── abc │ └── 1 └── abcd //同步test到/opt/abcd [root@RS1 ~]# rsync -avz test /opt/abcd/ sending incremental file list test/ test/abc/ test/abc/1 test/abcd/ sent 171 bytes received 51 bytes 444.00 bytes/sec total size is 0 speedup is 0.00 //查看效果 [root@RS1 ~]# tree /opt/abcd/ /opt/abcd/ └── test ├── abc │ └── 1 └── abcd //同時同步多個文件或文件夾 [root@RS1 ~]# touch abc [root@RS1 ~]# ls abc anaconda-ks.cfg [root@RS1 ~]# touch test [root@RS1 ~]# touch 1 [root@RS1 ~]# rsync -avz abc test 1 /opt/abc/ sending incremental file list 1 abc test sent 188 bytes received 73 bytes 522.00 bytes/sec total size is 0 speedup is 0.00 [root@RS1 ~]# tree /opt/abc/ /opt/abc/ ├── 1 ├── abc └── test 0 directories, 3 files
ssh協議非本地同步
//使用rsync實現本地文件同步到對端 [root@RS1 ~]# touch 123 [root@RS1 ~]# echo haha >123 [root@RS1 ~]# cat 123 haha [root@RS1 ~]# rsync -avz 123 root@192.168.100.133:/opt/ root@192.168.100.133's password: sending incremental file list 123 sent 90 bytes received 35 bytes 50.00 bytes/sec total size is 5 speedup is 0.04 [root@RS1 ~]# ssh root@192.168.100.133 root@192.168.100.133's password: Last login: Tue May 11 08:05:09 2021 from 192.168.100.132 [root@RS2 ~]# ls /opt/ 123 [root@RS2 ~]# cat /opt/123 haha
rsync+inotify
rsync與傳統的cp、tar備份方式相比,rsync具有安全性高、備份迅速、支持增量備份等優點,通過rsync可以解決對實時性要求不高的數據備份需求,例如定期的備份文件服務器數據到遠端服務器,對本地磁盤定期做數據鏡像等。
隨着應用系統規模的不斷擴大,對數據的安全性和可靠性也提出的更好的要求,rsync在高端業務系統中也逐漸暴露出了很多不足,首先,rsync同步數據時,需要掃描所有文件后進行比對,進行差量傳輸。如果文件數量達到了百萬甚至千萬量級,掃描所有文件將是非常耗時的。而且正在發生變化的往往是其中很少的一部分,這是非常低效的方式。其次,rsync不能實時的去監測、同步數據,雖然它可以通過linux守護進程的方式進行觸發同步,但是兩次觸發動作一定會有時間差,這樣就導致了服務端和客戶端數據可能出現不一致,無法在應用故障時完全的恢復數據。基於以上原因,rsync+inotify組合出現了!
Inotify是一種強大的、細粒度的、異步的文件系統事件監控機制,linux內核從2.6.13起,加入了Inotify支持,通過Inotify可以監控文件系統中添加、刪除,修改、移動等各種細微事件,利用這個內核接口,第三方軟件就可以監控文件系統下文件的各種變化情況,而inotify-tools就是這樣的一個第三方軟件。
在前面有講到,rsync可以實現觸發式的文件同步,但是通過crontab守護進程方式進行觸發,同步的數據和實際數據會有差異,而inotify可以監控文件系統的各種變化,當文件有任何變動時,就觸發rsync同步,這樣剛好解決了同步數據的實時性問題。
環境說明:
| 服務器類型 | IP地址 | 應用 | 操作系統 |
|---|---|---|---|
| 源服務器 | 192.168.100.132 | rsync inotify-tools 腳本 |
redhat8 |
| 目標服務器 | 192.168.100.133 | rsync | redhat8 |
需求:
- 把源服務器上/etc目錄實時同步到目標服務器的/tmp/下
在目標服務器上做以下操作:
//關閉防火牆與SELINUX [root@RS2 ~]# setenforce 0 [root@RS2 ~]# systemctl stop firewalld //安裝rsync服務端軟件 dnf -y install rsync //設置rsyncd.conf配置文件,這個文件默認不存在,需要自己編輯。注意:文件里的注釋需要去掉 [root@RS2 ~]# vim /etc/rsyncd.conf log file = /var/log/rsyncd.log # 日志文件位置,啟動rsync后自動產生這個文件,無需提前創 建 pidfile = /var/run/rsyncd.pid # pid文件的存放位置 lock file = /var/run/rsync.lock # 支持max connections參數的鎖文件 secrets file = /etc/rsync.pass # 用戶認證配置文件,里面保存用戶名稱和密碼,必須手動創>建這個文件 [etc_from_client] # 自定義同步名稱 path = /tmp/ # rsync服務端數據存放路徑,客戶端的數據將同步至此目錄 comment = sync etc from client uid = root # 設置rsync運行權限為root gid = root # 設置rsync運行權限為root port = 873 # 默認端口 ignore errors # 表示出現錯誤忽略錯誤 use chroot = no # 默認為true,修改為no,增加對目錄文件軟連接的備份 read only = no # 設置rsync服務端為讀寫權限 list = no # 不顯示rsync服務端資源列表 max connections = 200 # 最大連接數 timeout = 600 # 設置超時時間 auth users = admin # 執行數據同步的用戶名,可以設置多個,用英文狀態下逗號隔開 //設置文件權限 [root@RS2 ~]# echo "admin:123456" > /etc/rsync.pass [root@RS2 ~]# cat /etc/rsync.pass admin:123456 [root@RS2 ~]# chmod 600 /etc/rsync* [root@RS2 ~]# ll /etc/rsync* -rw-------. 1 root root 1145 5月 11 23:26 /etc/rsyncd.conf -rw-------. 1 root root 13 5月 11 23:26 /etc/rsync.pass
腳本實現rsync開機自啟並啟動:
[root@RS2 ~]# vim enable.sh #!/bin/bash dnf -y install xinetd systemctl enable --now xinetd cat > /etc/xinetd.d/rsync <<EOF service rsync { disable = no socket_type = stream wait = no user = root server = /usr/bin/rsync server_args = --daemon log_on_failure += USERID } EOF systemctl restart xinetd ss -antl [root@RS2 ~]# bash enable.sh
在源服務器上做以下操作:
//關閉防火牆與SELINUX [root@RS1 ~]# systemctl stop firewalld [root@RS1 ~]# setenforce 0 //安裝rsync [root@RS1 ~]# dnf -y install rsync //創建認證密碼,設置文件權限 [root@RS1 ~]# echo '123456' > /etc/rsync.pass //這個密碼文件名字自定義都行 [root@RS1 ~]# cat /etc/rsync.pass 123456 [root@RS1 ~]# chmod 600 /etc/rsync.pass [root@RS1 ~]# ll /etc/rsync.pass -rw------- 1 root root 7 5月 12 00:26 /etc/rsync.pass //在源服務器上創建測試目錄,然后在源服務器運行以下命令 [root@RS1 ~]# ls anaconda-ks.cfg [root@RS1 ~]# mkdir -pv /root/etc/test mkdir: 已創建目錄 '/root/etc' mkdir: 已創建目錄 '/root/etc/test' [root@RS1 ~]# rsync -avH --port 873 --progress --delete /root/etc/ admin@192.168.100.133::etc_from_client --password-file=/etc/rsync.pass sending incremental file list deleting systemd-private-5c6a8065c36b4727a2c7dcfd55edd79d-httpd.service-67QUvz/tmp/ deleting systemd-private-5c6a8065c36b4727a2c7dcfd55edd79d-httpd.service-67QUvz/ deleting .font-unix/ deleting .XIM-unix/ deleting .X11-unix/ deleting .Test-unix/ deleting .ICE-unix/ ./ test/ sent 77 bytes received 251 bytes 656.00 bytes/sec total size is 0 speedup is 0.00 //運行完成后,在目標服務器上查看,在/tmp目錄下有test目錄,說明數據同步成功 #RS2 [root@RS2 ~]# ls /tmp test
//安裝inotify-tools工具,實時觸發rsync進行同步 //查看服務器內核是否支持inotify [root@RS1 ~]# ll /proc/sys/fs/inotify/ 總用量 0 -rw-r--r-- 1 root root 0 5月 12 00:45 max_queued_events -rw-r--r-- 1 root root 0 5月 12 00:45 max_user_instances -rw-r--r-- 1 root root 0 5月 12 00:45 max_user_watches //如果有這三個max開頭的文件則表示服務器內核支持inotify //配置yum源 [root@RS1 yum.repos.d]# wget http://mirrors.163.com/.help/CentOS7-Base-163.repo [root@RS1 yum.repos.d]# sed -i 's/\$releasever/7/g' /etc/yum.repos.d/CentOS7-Base-163.repo [root@RS1 yum.repos.d]# sed -i 's/^enabled=.*/enabled=1/g' /etc/yum.repos.d/CentOS7-Base-163.repo [root@RS1 yum.repos.d]# yum -y install epel-release //安裝inotify-tools [root@RS1 ~]# dnf -y install make gcc gcc-c++ [root@RS1 yum.repos.d]# dnf -y install inotify-tools //寫同步腳本,此步乃最最重要的一步,請慎之又慎。讓腳本自動去檢測我們制定的目錄下 ,寫完配置之后吧注釋的內容刪掉 //文件發生的變化,然后再執行rsync的命令把它同步到我們的服務器端去 [root@RS1 ~]# vim /scripts/inotify.sh host=192.168.100.133 # 目標服務器的ip(備份服務器) src=/etc # 在源服務器上所要監控的備份目錄(此處可以自定義,但是要保證存在) des=etc_from_client # 自定義的模塊名,需要與目標服務器上定義的同步名稱一致 password=/etc/rsync.pass # 執行數據同步的密碼文件 user=admin # 執行數據同步的用戶名 inotifywait=/usr/bin/inotifywait $inotifywait -mrq --timefmt '%Y%m%d %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $src \ | while read files;do rsync -avzP --delete --timeout=100 --password-file=${password} $src $user@$host::$des echo "${files} was rsynced" >>/tmp/rsync.log 2>&1 done //啟動腳本 [root@RS1 ~]# nohup bash /scripts/inotify.sh & [1] 2960 //在源服務器上生成一個新文件 [root@RS1 ~]# ls /etc/httpd/ conf conf.d conf.modules.d logs modules run state [root@RS1 ~]# echo "hello world" > /etc/httpd/test [root@RS1 ~]# tail /tmp/rsync.log 20210512 01:43 /etc/httpd/testCREATE was rsynced 20210512 01:43 /etc/httpd/testMODIFY was rsynced //設置腳本開機自啟 [root@RS1 ~]# chmod +x /etc/rc.d/rc.local [root@RS1 ~]# ll /etc/rc.d/rc.local -rwxr-xr-x. 1 root root 474 2月 26 2019 /etc/rc.d/rc.local [root@RS1 ~]# echo 'nohup /bin/bash /scripts/inotify.sh' >> /etc/rc.d/rc.local [root@RS1 ~]# tail /etc/rc.d/rc.local # # In contrast to previous versions due to parallel execution during boot # this script will NOT be run after all other services. # # Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure # that this script will be executed during boot. touch /var/lock/subsys/local nohup /bin/bash /scripts/inotify.sh //到目標服務器上去查看是否把新生成的文件自動傳上去了: [root@RS2 ~]# ls /tmp etc [root@RS2 ~]# ls /tmp/etc/ Display all 183 possibilities? (y or n) //由此可見,已將源服務器的/etc目錄整個同步到了目標服務器,且新增的test文件也自動同步了
