若是服務器之間須要保持某些文件的一致,咱們可使用scp
來複制,若是須要長期保持一致,能夠配合crontab
腳原本使用。可是此時咱們有更優的方式,就是rsync+crontab
來實現定時增量傳輸保持文件一致。html
rsync
功能很強大,網上的資料也都很全,這裏作一些簡單的彙總。linux
rsync
原理這一小節內容大幅度轉載了 RSYNC 的核心算法 的內容,由於原文章寫的太好,就再也不狗尾續貂了,感興趣的能夠直接查看原文。他的翻譯原文是: The rsync algorithm。
rsync
是linux
下同步文件的一個高效算法,用於同步更新兩處計算機的文件和目錄,並適當利用查找文件中的不一樣塊以減小數據傳輸。rsync
的主要特色就是增量傳輸,只對變動的部分進行傳送。算法
假如咱們如今須要同步兩個文件保持一致,而且只想傳送不一樣的部分,那麼咱們就須要對兩邊的文件作diff
,可是這兩個問題在兩臺不一樣的機器上,沒法作diff
。若是咱們作diff
,就要把一個文件傳到另外一臺機器上作diff
,但這樣一來,咱們就傳了整個文件,這與咱們只想傳輸不一樣部的初衷相背。因而咱們就要想一個辦法,讓這兩邊的文件見不到面,但還能知道它們間有什麼不一樣。這就是rsync
的算法。shell
rsync
同步算法咱們將同步源文件名稱爲fileSrc
,同步目的文件叫fileDst
。數組
Checksum
算法首先,咱們會把fileDst
的文件平均切分紅若干個小塊,好比每塊512
個字節(最後一塊會小於這個數),而後對每塊計算兩個checksum
:服務器
rolling checksum
,是弱checksum
,32
位的checksum
checksum
,128
位的,之前用md4
,如今用md5 hash
算法。爲何要這樣?由於若干年前的硬件上跑md4
的算法太慢了,因此,咱們須要一個快算法來鑑別文件塊的不一樣,可是弱的adler32
算法碰撞機率過高了,因此咱們還要引入強的checksum
算法以保證兩文件塊是相同的。也就是說,弱的checksum
是用來區別不一樣,而強的是用來確認相同。網絡
同步目標端會把fileDst
的一個checksum
列表傳給同步源,這個列表裏包括了三個東西,rolling checksum(32bits),md5 checksume(128bits)
,文件塊編號。數據結構
同步源機器拿到了這個列表後,會對fileSrc
作一樣的checksum
,而後和fileDst
的checksum
作對比,這樣就知道哪些文件塊改變了。ssh
可是,聰明的你必定會有如下兩個疑問:工具
若是我fileSrc
這邊在文件中間加了一個字符,這樣後面的文件塊都會位移一個字符,這樣就徹底和fileDst
這邊的不同了,但理論上來講,我應該只須要傳一個字符就行了。這個怎麼解決?
若是這個checksum
列表特別長,而個人兩邊的相同的文件塊可能並非同樣的順序,那就須要查找,線性的查找起來應該特別慢吧。這個怎麼解決?
很好,讓咱們來看一下同步源端的算法。
checksum
查找算法同步源端拿到fileDst
的checksum
數組後,會把這個數據存到一個hash table
(特殊的數據結構體,能夠快速檢索)中,用rolling checksum
作hash
,以便得到O(1)
時間複雜度的查找性能。這個hash table
是16bits
的,因此,hash table
的尺寸是2的16次方
,對rolling checksum
的hash
會被散列到0 到 2^16 – 1
中的某個整數值。
fileSrc
的第一個文件塊(咱們假設的是512
個長度),也就是從fileSrc
的第1
個字節到第512
個字節,取出來後作rolling checksum
計算。計算好的值到hash
表中查。fileDst
中有潛在相同的文件塊,因而就再比較md5
的checksum
,由於rolling checksume
太弱了,可能發生碰撞。因而還要算md5
的128bits
的checksum
,這樣一來,咱們就有 2^-(32+128) = 2^-160
的機率發生碰撞,這過小了能夠忽略。若是rolling checksum
和md5 checksum
都相同,這說明在fileDst
中有相同的塊,咱們須要記下這一塊在fileDst
下的文件編號。fileSrc
的rolling checksum
沒有在hash table
中找到,那就不用算md5 checksum
了。表示這一塊中有不一樣的信息。總之,只要rolling checksum
或 md5 checksum
其中有一個在fileDst
的checksum hash
表中找不到匹配項,那麼就會觸發算法對fileSrc
的rolling
動做。因而,算法會住後step 1
個字節,取fileSrc
中字節2-513
的文件塊要作checksum,go to (1.)
– 如今你明白什麼叫rolling checksum
了吧。fileSrc
相鄰兩次匹配中的那些文本字符,這些就是咱們要往同步目標端傳的文件內容了。
最終在同步源這端,咱們的rsync
算法可能會獲得這個樣子的一個數據數組,圖中,紅色塊表示在目標端已匹配上,不用傳輸(注:我專門在其中顯示了兩塊chunk #5
,表明數據中有複製的地方,不用傳輸),而白色的地方就是須要傳輸的內容(注意:這些白色的塊是不定長的),這樣,同步源這端把這個數組(白色的就是實際內容,紅色的就放一個標號)壓縮傳到目的端,在目的端的rsync
會根據這個表從新生成文件,這樣,同步完成。
最後想說一下,對於某些壓縮文件使用rsync
傳輸可能會傳得更多,由於被壓縮後的文件可能會很是的不一樣。對此,對於gzip
和bzip2
這樣的命令,記得開啓 「rsyncalbe」
模式。
rsync
的使用一樣的,這一小節內容也是大幅度轉載了 第2章 rsync(一):基本命令和用法 的內容,由於原文章很全面,感興趣的能夠直接查看原文。
rsync
是實現增量備份的工具。配合任務計劃,rsync
能實現定時或間隔同步,配合inotify
或sersync
,能夠實現觸發式的實時同步。它的目的是實現本地主機和遠程主機上的文件同步(包括本地推到遠程,遠程拉到本地兩種同步方式),也能夠實現本地不一樣路徑下文件的同步,但不能實現遠程路徑1
到遠程路徑2
之間的同步(scp
能夠實現)。
rsync
同步過程當中由兩部分組成:決定哪些文件須要同步的檢查模式以及文件同步時的同步模式。
rsync
使用"quick check"
算法快速檢查源文件和目標文件的大小、mtime
(修改時間)是否一致,若是不一致則須要傳輸。固然,也能夠經過在rsync
命令行中指定某些選項來改變quick check
的檢查模式,好比"--size-only"
選項表示"quick check"
將僅檢查文件大小不一樣的文件做爲待傳輸文件。rsync
支持很是多的選項,其中檢查模式的自定義性是很是有彈性的。rsync
也提供很是多的選項使得同步模式變得更具彈性。相對來講,爲rsync
手動指定同步模式的選項更常見一些,只有在有特殊需求時才指定檢查模式,由於大多數檢查模式選項均可能會影響rsync
的性能。
rsync
四種工做方式rsync
的基礎語法爲:rsync [OPTION...] SRC... [DEST]
支持的參數高達一百多個,最經常使用的選項組合是"avz"
,即壓縮和顯示部分信息,並以歸檔模式傳輸。詳細的能夠參考 博客園-man rsync翻譯(rsync命令中文手冊),下面是部分參數說明:
-v:顯示rsync過程當中詳細信息。可使用"-vvvv"獲取更詳細信息。 -P:顯示文件傳輸的進度信息。(實際上"-P"="--partial --progress",其中的"--progress"纔是顯示進度信息的)。 -n --dry-run :僅測試傳輸,而不實際傳輸。常和"-vvvv"配合使用來查看rsync是如何工做的。 -a --archive :歸檔模式,表示遞歸傳輸並保持文件屬性。等同於"-rtopgDl"。 -r --recursive:遞歸到目錄中去。 -t --times:保持mtime屬性。強烈建議任什麼時候候都加上"-t",不然目標文件mtime會設置爲系統時間,致使下次更新 :檢查出mtime不一樣從而致使增量傳輸無效。 -o --owner:保持owner屬性(屬主)。 -g --group:保持group屬性(屬組)。 -p --perms:保持perms屬性(權限,不包括特殊權限)。 -D :是"--device --specials"選項的組合,即也拷貝設備文件和特殊文件。 -l --links:若是文件是軟連接文件,則拷貝軟連接自己而非軟連接所指向的對象。 -z :傳輸時進行壓縮提升效率。 -R --relative:使用相對路徑。意味着將命令行中指定的全路徑而非路徑最尾部的文件名發送給服務端,包括它們的屬性。用法見下文示例。 --size-only :默認算法是檢查文件大小和mtime不一樣的文件,使用此選項將只檢查文件大小。 -u --update :僅在源mtime比目標已存在文件的mtime新時才拷貝。注意,該選項是接收端判斷的,不會影響刪除行爲。 -d --dirs :以不遞歸的方式拷貝目錄自己。默認遞歸時,若是源爲"dir1/file1",則不會拷貝dir1目錄,使用該選項將拷貝dir1但不拷貝file1。 --max-size :限制rsync傳輸的最大文件大小。可使用單位後綴,還能夠是一個小數值(例如:"--max-size=1.5m") --min-size :限制rsync傳輸的最小文件大小。這能夠用於禁止傳輸小文件或那些垃圾文件。 --exclude :指定排除規則來排除不須要傳輸的文件。 --delete :以SRC爲主,對DEST進行同步。多則刪之,少則補之。注意"--delete"是在接收端執行的,因此它是在 :exclude/include規則生效以後才執行的。 -b --backup :對目標上已存在的文件作一個備份,備份的文件名後默認使用"~"作後綴。 --backup-dir:指定備份文件的保存路徑。不指定時默認和待備份文件保存在同一目錄下。 -e :指定所要使用的遠程shell程序,默認爲ssh。 --port :鏈接daemon時使用的端口號,默認爲873端口。 --password-file:daemon模式時的密碼文件,能夠從中讀取密碼實現非交互式。注意,這不是遠程shell認證的密碼,而是rsync模塊認證的密碼。 -W --whole-file:rsync將再也不使用增量傳輸,而是全量傳輸。在網絡帶寬高於磁盤帶寬時,該選項比增量傳輸更高效。 --existing :要求只更新目標端已存在的文件,目標端還不存在的文件不傳輸。注意,使用相對路徑時若是上層目錄不存在也不會傳輸。 --ignore-existing:要求只更新目標端不存在的文件。和"--existing"結合使用有特殊功能,見下文示例。 --remove-source-files:要求刪除源端已經成功傳輸的文件。
rsync [OPTION...] SRC... [DEST]
shell
和遠程主機通訊Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST] Push: rsync [OPTION...] SRC... [USER@]HOST:DEST
rsync daemon
Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST] rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST] Push: rsync [OPTION...] SRC... [USER@]HOST::DEST rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
前二者的本質是經過管道通訊,即便是遠程shell
。而方式(3)
則是讓遠程主機上運行rsync
服務,使其監聽在一個端口上,等待客戶端的鏈接。
路徑的格式能夠是本地路徑,也能夠是使用user@host:path
或user@host::path
的遠程路徑,若是主機和path
路徑之間使用單個冒號隔開,表示使用的是遠程shell
通訊方式,而使用雙冒號隔開的則表示的是鏈接rsync daemon
。另外,鏈接rsync daemon
時,還提供了URL
格式的路徑表述方式rsync://user@host/path
。
shell
臨時啓動一個rsync daemon
rsync [options] --rsh=ssh auth_user@host::module rsync [options] --rsh="ssh -l ssh_user" auth_user@host::module rsync [options] -e "ssh -l ssh_user" auth_user@host::module rsync [options] -e "ssh -l ssh_user" rsync://auth_user@host/module
這不一樣於方式(3)
,它不要求遠程主機上事先啓動rsync
服務,而是臨時派生出rsync daemon
,它是單用途的一次性daemon
,僅用於臨時讀取daemon
的配置文件,當這次rsync
同步完成,遠程shell
啓動的rsync daemon
進程也會自動消逝。此通訊方式的命令行語法格式同"Access via rsync daemon"
,但要求options
部分必須明確指定"--rsh"
選項或其短選項"-e"
。
# 將/etc/fstab拷貝到/tmp目錄下 rsync /etc/fstab /tmp # 將/etc/cron.d目錄拷貝到/tmp下 rsync -r /etc/cron.d /tmp # 將/etc/cron.d目錄拷貝到/tmp下,但要求在/tmp下也生成etc子目 rsync -R -r /etc/cron.d /tmp # 拷貝源路徑較長,但只保留一部分目錄結構,使用一個點表明相對路徑的起始位置 rsync -R -r /var/./log/anaconda /tmp # 對遠程目錄下已存在文件作備份,備份後綴爲"~",使用"--suffix"指定後綴 rsync -R -r --backup /var/./log/anaconda /tmp # 指定備份文件保存路徑,默認將不會加備份後綴,使用"--suffix"顯式指定後綴 rsync -R -r --backup --backup-dir=/tmp/log_back /var/./log/anaconda /tmp # .指定ssh鏈接參數,如端口、鏈接的用戶、ssh選項等 rsync -e "ssh -p 22 -o StrictHostKeyChecking=no" /etc/fstab 172.16.10.5:/tmp # 使用"--existing"選項使得只更新目標端已存在的文件 rsync -r -v --existing /tmp/a/ /tmp/b # "--ignore-existing"更新目標端不存在的文件 rsync -r -v --ignore-existing /tmp/a/ /tmp/b # "--remove-source-files"刪除源端文件 rsync -r -v --remove-source-files /tmp/a/anaconda /tmp/a/audit /tmp # 使用"--exclude"選項指定排除規則,排除那些不須要傳輸的文件。 rsync -r -v --exclude="anaconda/*.log" /var/log/anaconda /var/log/audit /tmp
若是僅有一個SRC
或DEST
參數,則將以相似於"ls -l"
的方式列出源文件列表(只有一個路徑參數,總會認爲是源文件),而不是複製文件。
源路徑若是是一個目錄的話,帶上尾隨斜線和不帶尾隨斜線是不同的,不帶尾隨斜線表示的是整個目錄包括目錄自己,帶上尾隨斜線表示的是目錄中的文件,不包括目錄自己。
# 在/tmp目錄下建立etc目錄 [root@xuexi ~]# rsync -a /etc /tmp # 不會在/tmp目錄下建立etc目錄,源路徑/etc/中的全部文件都直接放在/tmp目錄下 [root@xuexi ~]# rsync -a /etc/ /tmp