參考資料:駿馬金龍的rsync系列。該博主的博文質量很好,推薦大家關註。 環境 操作系統:CentOS Linux release 7.5.1804 (Core) 軟體:rsync version 3.1.2 protocol version 31 前言 rsync可以實現scp的部分遠程複製功能( ...
參考資料:駿馬金龍的rsync系列。該博主的博文質量很好,推薦大家關註。
環境
操作系統:CentOS Linux release 7.5.1804 (Core)
軟體:rsync version 3.1.2 protocol version 31
前言
rsync可以實現scp的部分遠程複製功能(支持本地到遠程複製和遠程到本地複製,但是不支持遠程到遠程複製;scp可以支持遠程到遠程複製)、cp的本地複製功能、rm的刪除功能和“ls -l”的顯示詳細信息文件列表功能。
註意,rsync的初衷是實現兩端主機之間的數據同步,上述功能只是作為輔助,並且其實現方式是與scp/cp/rm/ls這些命令不同的。
rsync有自己的一套演算法以及演算法實現機制,日常使用的話可以無需瞭解。但是,如果想要看懂rsync的man手冊或者官方文檔,想要通過-vvvv選項看懂rsync的執行過程,那麼還是有必要瞭解rsync的原理的。
同步基礎
同步涉及到了源文件(源主機、發送端)和目標文件(目標主機、接收端)、本地主機和遠程主機、以及以哪邊的主機上的文件為基準的概念。以誰為基準,就是以誰作為源文件。
- 想讓本地主機上的文件和遠程主機上的文件保持同步。則以遠程主機上的文件為基準(即作為源文件),將其拉取到本地主機覆蓋本地主機的文件(即作為目標文件)。
- 想讓遠程主機上的文件和本地主機上的文件保持同步。則以本地主機上的文件為基準(即作為源文件),將其推送到遠程主機覆蓋遠程主機的文件(即作為目標文件)。
- 本地主機和遠程主機,既可以作為源主機/發送端,也可以作為目標主機/接收端,看具體的情況而定。
同步的過程,還涉及到其他的問題。
- 是否刪除源主機上沒有但是目標主機上多出來的文件?
- 目標文件的mtime比源文件的mtime更(gèng)新的時候,是否覆蓋?
- 遇到字元鏈接時,是同步字元鏈接本身還是其所指向的文件?即是否追蹤字元鏈接文件?
- 目標文件已存在時,是否做備份?
- 等等其他情況。
上面這些操作,都是需要rsync來完成的,這也就是為什麼在使用rsync的時候要求源和目標主機都需要安裝有rsync程式包。
rsync的同步由檢查模式和同步模式兩部分構成。
檢查模式
檢查模式用於檢查哪些文件應該被同步,哪些文件不應該被同步。比如--exclude選項排除了不應該被同步的文件。預設情況下,rsync使用quick check演算法來檢查源文件和目標文件的size(文件大小)與mtime。當size或者mtime不同的時候,就會判定文件應該被同步。
可以通過一些選項來修改檢查模式,例如--size-only用於指明將僅檢查文件的size而不檢查mtime。
還有其他的選項也可以用於修改檢查模式,彈性十足。
同步模式
同步模式用於處理上面所說的“是否刪除本地主機上沒有但是遠程主機上多出來的文件?”之類的問題。同步模式也有許多選項可以指定,也是彈性十足。
一般情況下我們是修改同步模式,少數情況下才會修改檢查模式,因為後者的修改容易引起性能的較大改動(例如--checksum)或者沒有正確同步應該同步的文件(例如--size-only)。
三種工作方式
rsync有三種工作方式,即三種語法格式,如下。
Local: rsync [OPTION...] SRC... [DEST] Access via remote shell: Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST] Push: rsync [OPTION...] SRC... [USER@]HOST:DEST Access via 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
- 第一種方式是上述的Local部分,為本地主機內部的同步。
- 第二種方式是上述的remote shell部分,為不同主機通過遠程shell實現同步。
- 第三種方式是上述的rsync daemon部分,為不同主機通過網路套接字實現同步。這種方式在指定daemon的時候有兩種形式。有雙冒號形式和URL形式,都是可以的,個人傾向於URL形式,比較不會和單冒號形式相似。前面演示的示例都是本地主機或者遠程shell,最後再單獨講rsync daemon方式。
前兩者的本質是基於管道;第三種是需要先在遠程主機上運行一個daemon,監聽在某個埠上,然後本地主機通過網路套接字與其通信。
還有一種特殊的方式,是基於遠程shell連接上之後,在遠程主機上臨時運行一個daemon,當數據同步完畢後,daemon也會結束。這種方式的命令行語法類似rsync daemon模式,不同的點在於選項需要指明-e或者--rsh。
本文中我們將其稱為“臨時daemon”,註意,這隻是個人對其稱呼,非官方。
命令的參數可以有多個;當指定多個的時候,只有最後一個表示目標文件,其餘都為源文件,目標文件若不存在則自動創建為目錄,若存在則必須得是目錄,否則報錯。
[root@C7 ~]# file /tmp/1.txt /tmp/1.txt: empty [root@C7 ~]# rsync /etc/fstab /etc/inittab /tmp/1.txt ERROR: destination must be a directory when copying more than 1 file rsync error: errors selecting input/output files, dirs (code 3) at main.c(623) [Receiver=3.1.2]
如果參數只有一個SRC的話,那麼等同於“ls -l”。
[root@c7-client ~]# rsync /etc/fstab -rw-r--r-- 487 2018/12/18 11:46:20 fstab [root@c7-client ~]# rsync /etc/ssh/ drwxr-xr-x 225 2018/12/18 12:04:37 . -rw-r--r-- 581,843 2018/04/11 12:21:29 moduli -rw-r--r-- 2,276 2018/04/11 12:21:29 ssh_config -rw-r----- 227 2018/12/18 12:04:37 ssh_host_ecdsa_key -rw-r--r-- 162 2018/12/18 12:04:37 ssh_host_ecdsa_key.pub -rw-r----- 387 2018/12/18 12:04:37 ssh_host_ed25519_key -rw-r--r-- 82 2018/12/18 12:04:37 ssh_host_ed25519_key.pub -rw-r----- 1,679 2018/12/18 12:04:35 ssh_host_rsa_key -rw-r--r-- 382 2018/12/18 12:04:35 ssh_host_rsa_key.pub -rw------- 3,907 2018/04/11 12:21:29 sshd_config [root@c7-client ~]# rsync root@192.168.17.7:/etc/fstab root@192.168.17.7's password: -rw-r--r-- 465 2018/09/27 15:49:45 fstab [root@c7-client ~]# rsync root@192.168.17.7:/etc/ssh/ [email protected]'s password: drwxr-xr-x 225 2018/09/27 17:28:23 . -rw-r--r-- 581,843 2018/04/11 12:21:29 moduli -rw-r--r-- 2,276 2018/04/11 12:21:29 ssh_config -rw-r----- 227 2018/09/27 16:02:33 ssh_host_ecdsa_key -rw-r--r-- 162 2018/09/27 16:02:33 ssh_host_ecdsa_key.pub -rw-r----- 387 2018/09/27 16:02:33 ssh_host_ed25519_key -rw-r--r-- 82 2018/09/27 16:02:33 ssh_host_ed25519_key.pub -rw-r----- 1,679 2018/09/27 16:02:33 ssh_host_rsa_key -rw-r--r-- 382 2018/09/27 16:02:33 ssh_host_rsa_key.pub -rw------- 3,905 2018/09/27 17:28:23 sshd_config
當使用遠程shell的時候,會提示我們輸入遠程主機的用戶密碼。由於遠程shell方式是基於SSH,因此可以事先配置好SSH的免密登錄,這樣就無需密碼了。
[root@c7-client ~]# rsync root@192.168.17.7:/etc/fstab -rw-r--r-- 465 2018/09/27 15:49:45 fstab
本地主機文件和目錄的複製,類似cp命令。
[root@c7-client ~]# rsync /etc/fstab /tmp/ [root@c7-client ~]# ls -l /etc/fstab /tmp/fstab -rw-r--r--. 1 root root 487 Dec 18 11:46 /etc/fstab -rw-r--r--. 1 root root 487 Dec 19 19:04 /tmp/fstab [root@c7-client ~]# rsync -r /etc/ssh /tmp/ [root@c7-client ~]# ls /{etc,tmp}/ssh/ /etc/ssh/: moduli ssh_config sshd_config ssh_host_ecdsa_key ssh_host_ecdsa_key.pub ssh_host_ed25519_key ssh_host_ed25519_key.pub ssh_host_rsa_key ssh_host_rsa_key.pub /tmp/ssh/: moduli ssh_config sshd_config ssh_host_ecdsa_key ssh_host_ecdsa_key.pub ssh_host_ed25519_key ssh_host_ed25519_key.pub ssh_host_rsa_key ssh_host_rsa_key.pub
複製或者同步目錄的時候,需要註意一點,如果源目錄的末尾沒有斜線,則表示將源目錄整個複製到目標目錄下,就如同上面的例子;
如果源目錄的末尾有斜線,則表示將源目錄下的內容複製到目標目錄下,如下所示。
[root@c7-client ~]# rsync -r /etc/ssh/ testdir/ [root@c7-client ~]# ls /etc/ssh/ testdir/ /etc/ssh/: moduli ssh_config sshd_config ssh_host_ecdsa_key ssh_host_ecdsa_key.pub ssh_host_ed25519_key ssh_host_ed25519_key.pub ssh_host_rsa_key ssh_host_rsa_key.pub testdir/: moduli ssh_config sshd_config ssh_host_ecdsa_key ssh_host_ecdsa_key.pub ssh_host_ed25519_key ssh_host_ed25519_key.pub ssh_host_rsa_key ssh_host_rsa_key.pub
遠程shell之間的文件同步。
[root@c7-client ~]# rsync c7-client.txt root@192.168.17.7:/root/ [root@c7-client ~]# rsync root@192.168.17.7:/root/c7.txt .
遠程shell之間的目錄同步。
[root@c7-client ~]# touch testdir/rsync{1,2,3}.txt [root@c7-client ~]# rsync -r testdir/ root@192.168.17.7:/root/ [root@C7 ~]# ls -l /root/rsync{1,2,3}.txt -rw-r--r-- 1 root root 0 Dec 19 19:17 /root/rsync1.txt -rw-r--r-- 1 root root 0 Dec 19 19:17 /root/rsync2.txt -rw-r--r-- 1 root root 0 Dec 19 19:17 /root/rsync3.txt [root@c7-client ~]# rsync -r root@192.168.17.7:/root/rrr . [root@c7-client ~]# ls -l rrr/ total 0 -rw-r--r--. 1 root root 0 Dec 19 19:19 l.txt -rw-r--r--. 1 root root 0 Dec 19 19:19 w.txt -rw-r--r--. 1 root root 0 Dec 19 19:19 z.txt
選項與示例
-v, --verbose:用於顯示同步中的詳細信息,-vvvv可以顯示更詳細的信息,一般是用於排錯的時候使用。v的個數越多,顯示的信息越詳細。
--partial:預設情況下,當傳輸中斷的時候,rsync會將已傳輸一半的目標文件刪除;如果使用該選項,則不會刪除,這樣子可以提高再次傳輸的速度,感覺類似於斷點重傳。
--progress:在同步的時候顯示進度,類似如下。
782448 63% 110.64kB/s 0:00:04
-P:該選項是--partial和--progress的結合,當同步的時間較長(文件較大較多或者網路不佳)的時候,可以使用該選項。
-n, --dry-run:用於測試,不會真正執行同步操作,而是模擬真實操作,並且模擬真實的輸出,常配合-v或者-vvvv來查看rsync是否執行正常。
-a, --archive:歸檔模式,等同於-rlptgoD,它保留了源文件的大部分元數據。但是它不包含-H選項,因為查找多鏈接的文件太消耗資源。
-r, --recursive:遞歸,用於同步目錄。如果不加該選項,當源文件是一個目錄的時候,會跳過,並返回被跳過的目錄名稱。
[root@C7 tmp]# rsync -v /foo/ /tmp/ skipping directory . sent 16 bytes received 12 bytes 56.00 bytes/sec total size is 0 speedup is 0.00 [root@C7 tmp]# rsync -v /foo /tmp/ skipping directory foo sent 16 bytes received 12 bytes 56.00 bytes/sec total size is 0 speedup is 0.00
這裡從輸出信息中也可以看出源文件如果是目錄,那麼末尾是否帶斜線的差異。
[root@C7 tmp]# rsync -rv /foo/ /tmp/ sending incremental file list bar/baz.c sent 131 bytes received 36 bytes 334.00 bytes/sec total size is 0 speedup is 0.00
-t, --times:保留文件的mtime,由於rsync預設檢查模式使用quick check演算法,因此建議每次同步都應該使用-t或者-a選項,否則發送端每次都會將很可能是相同的文件加入文件列表,導致了系統資源的浪費。
-o, --owner:保留文件的屬主。
-g, --group:保留文件的屬組。
--chown=USER:GROUP:文件同步後修改目標文件的ownership。該選項其實等同於“--usermap=*:USER --groupmap=*:GROUP”。不過該選項的實現是內部調用了--usermap和--groupmap,因此該選項不可以與這兩個選項混合使用。如果想要讓--chown正常使用,不可缺少-o和-g選項。
-p, --perms:保留文件的讀寫執行許可權,不包含其他特殊許可權。
--chmod:文件同步後修改目標文件的許可權。可根據文件是普通文件或者目錄分別設置不同的許可權。如果是普通文件則會加上首碼F,目錄則會加上首碼D。用法類似如下。
--chmod=Dg+s,ug+w,Fo-w,+X --chmod=D2775,F664
如果想要讓--chown正常使用,不可缺少-o和-g選項。
因此,如果想要讓--chown和--chmod都正常使用的話,使用-a選項即可!但是具體的原因目前未知,應該是rsync對待所有權(ownership)和許可權(permission)的理解與我們人腦不同。
讓我們來驗證一下-togp選項的作用,在c7-client主機上創建了一個空文件rsync.txt,並設置了許可權和ownership,然後同步至C7主機。可以發現同步後,文件的許可權、所有權以及mtime都發生了改變。
[root@c7-client ~]# ls -l rsync.txt -rw-rw-rw-. 1 haimianbb haimianbb 0 Dec 25 10:06 rsync.txt [root@c7-client ~]# rsync -v rsync.txt root@192.168.17.7:/tmp/rsync.txt rsync.txt sent 83 bytes received 35 bytes 236.00 bytes/sec total size is 0 speedup is 0.00 [root@C7 ~]# ls -l /tmp/rsync.txt -rw-r--r-- 1 root root 0 Dec 25 10:12 /tmp/rsync.txt
當我們使用了-togp選項之後,文件的許可權、mtime和所有權都保持了。
[root@c7-client ~]# rsync -vtogp rsync.txt root@192.168.17.7:/tmp/rsync.txt rsync.txt sent 113 bytes received 35 bytes 296.00 bytes/sec total size is 0 speedup is 0.00 [root@C7 ~]# ls -l /tmp/rsync.txt -rw-rw-rw- 1 haimianbb haimianbb 0 Dec 25 10:06 /tmp/rsync.txt
-D:等同於--devices和--specials的結合,用於同步字元設備、塊設備以及特殊文件(socket)。
-l, --links:當遇到字元鏈接的時候,在遠程主機上創建相同的字元鏈接文件。
預設情況下,字元鏈接文件是非普通文件,會被rsync跳過。
[root@C7 tmp]# cat /tmp/name.txt zhangwenlong [root@C7 tmp]# ln -s /tmp/name.txt /tmp/name.link [root@C7 tmp]# ls -l name.link lrwxrwxrwx 1 root root 13 Dec 25 17:32 name.link -> /tmp/name.txt [root@C7 tmp]# rsync -v name.link /root/name.rsync skipping non-regular file "name.link" sent 43 bytes received 54 bytes 194.00 bytes/sec total size is 13 speedup is 0.13
使用-l選項就可以同步字元鏈接文件了,同步後的文件也是一個字元鏈接文件。
[root@C7 tmp]# rsync -vl name.link /root/name.rsync name.link -> /tmp/name.txt sent 60 bytes received 19 bytes 158.00 bytes/sec total size is 13 speedup is 0.16 [root@C7 tmp]# ls -l /root/name.rsync lrwxrwxrwx 1 root root 13 Dec 25 17:35 /root/name.rsync -> /tmp/name.txt [root@C7 tmp]# cat /root/name.rsync zhangwenlong
-z, --compress:傳輸之前是否對數據進行壓縮。可以留意到壓縮後,發送的位元組數降低了。
[root@C7 tmp]# rsync -v /etc/inittab /tmp/inittab inittab sent 590 bytes received 35 bytes 1,250.00 bytes/sec total size is 511 speedup is 0.82 [root@C7 tmp]# rsync -vz /etc/inittab /tmp/inittab inittab sent 364 bytes received 35 bytes 798.00 bytes/sec total size is 511 speedup is 1.28
-R, --relative:使用相對路徑。意味著會將命令行中完整的路徑名稱發送給遠程主機,而不是只發送最後一部分的文件名。
我們先來看一下預設情況下的行為。複製/foo/bar/baz.c到/tmp/目錄下的時候,僅會在/tmp/目錄下創建baz.c文件。(從-v結果來看,應理解為僅將源文件“/foo/bar/baz.c”中的最後一部分“baz.c”加入了文件列表)
[root@C7 ~]# rsync -v /foo/bar/baz.c /tmp/ baz.c sent 78 bytes received 35 bytes 226.00 bytes/sec total size is 0 speedup is 0.00
如果增加了-R選項。則是在/tmp/目錄下創建了完整的目錄結構。這是因為-R選項使得發送端rsync將整個源文件路徑“/foo/bar/baz.c”加入了文件列表。
[root@C7 ~]# rsync -vR /foo/bar/baz.c /tmp/ /foo/ /foo/bar/ /foo/bar/baz.c sent 128 bytes received 41 bytes 338.00 bytes/sec total size is 0 speedup is 0.00 [root@C7 ~]# tree /tmp/foo/ /tmp/foo/ └── bar └── baz.c 1 directory, 1 file
像“foo/”和“foo/bar/”這種額外的路徑元素,我們就稱其為隱式目錄(implied directories)。如果相對路徑涉及到字元鏈接的話,可能會有特殊情況,要看一下man手冊。
有的時候你可能只希望在接收端創建部分源文件路徑,那麼可以在源文件路徑中插入一個“.”和“/”。
[root@C7 tmp]# rsync -vR /foo/./bar/baz.c /tmp/ bar/ bar/baz.c sent 100 bytes received 38 bytes 276.00 bytes/sec total size is 0 speedup is 0.00
這樣子相對路徑就是從bar開始的了。
--size-only:修改rsync預設的quick check演算法,僅檢查兩端文件大小。個人建議不要帶上該選項,雖然檢查的複雜度降低了,可能會提升性能,但是可能出現內容不同的文件沒得到正確的同步,在特定的環境下可能造成嚴重的後果。
就像這個例子中所示,1.txt和2.txt明明文件內容不一致,卻因為--size-only選項使得它們沒有被同步。
[root@C7 tmp]# ls -l {1,2}.txt -rw-r--r-- 1 root root 9 Dec 21 17:21 1.txt -rw-r--r-- 1 root root 9 Dec 21 17:22 2.txt [root@C7 tmp]# diff {1,2}.txt 1c1 < 12345678 --- > 87654321 [root@C7 tmp]# rsync -v --size-only {1,2}.txt sent 39 bytes received 12 bytes 102.00 bytes/sec total size is 9 speedup is 0.18 [root@C7 tmp]# diff {1,2}.txt 1c1 < 12345678 --- > 87654321
-c, --checksum:修改rsync預設的quick check演算法,通過檢驗碼的方式檢查兩端的文件內容是否一致,生成校驗碼會引起兩端產生大量的磁碟I/O,因此一般是不會啟用該選項。
-u, --update:如果目標文件存在且mtime新於源文件的話,則跳過。如果目標文件存在且mtime等於源文件的話,則判斷size,size同則不同步,size不同則同步。該選項是傳輸規則,並不是exclude,因此不會影響文件進入文件列表,因此不會影響目標文件上的刪除操作。
-d, --dirs:用於拷貝目錄本身,但是不會拷貝目錄下的文件。有別於-r, --recursive。但是如果源文件是以“.”或者斜杠結尾的話,那麼還是會將目錄下的內容拷貝至目標文件。如果-r和-d同時使用的話,那麼-r優先。
--max-size=SIZE:限制傳輸的文件的最大size。可以帶上單位尾碼“K、KiB、M、MiB、G、GiB”,這是以1024為乘數,如果想要以1000為乘數的話,則使用“KB、MB和GB”。大小寫均可。
--min-size=SIZE:限制傳輸的文件的最小size。其他說明類似上面的--max-size,避免傳輸較小的文件或者垃圾文件。
--exclude=PATTERN:用於排除文件,被排除的文件不會被同步。涉及到man手冊中的過濾規則(FILTER RULE)。後面會詳述。
--exclude-from=FILE:排除文件,即當需要排除的PATTERN較多的時候,可以將每一個PATTERN都寫入該文件中,每個PATTERN占一行。空行以及以“#”或者“;”開頭的行會被忽略。FILE為“-”表示讀取STDIN(標準輸入)。
--delete:刪除接收端中不存在於發送端的額外的文件,僅作用於那些已經同步了的目錄。後面會詳述。
-b, --backup:當目標文件已經存在的時候,同步操作即將覆蓋或者同步操作(--delete)即將刪除目標文件的時候,對其進行備份。
[root@C7 tmp]# rsync -vb /foo/bar/baz.c /tmp/ baz.c sent 78 bytes received 35 bytes 226.00 bytes/sec total size is 0 speedup is 0.00 [root@C7 tmp]# ls -l /tmp/baz.c* -rw-r--r-- 1 root root 0 Dec 21 17:28 /tmp/baz.c -rw-r--r-- 1 root root 0 Dec 21 17:28 /tmp/baz.c~
即便反覆執行,備份文件的文件名依然是“baz.c~”。
--backup-dir=DIR:指定備份文件的目錄。預設的備份目錄是在目標文件的當前目錄。
若備份目錄不存在,則會自動創建,並回顯。
[root@C7 tmp]# rsync -vb --backup-dir=/tmp/back/ /foo/bar/baz.c /tmp/ (new) backup_dir is /tmp/back baz.c sent 78 bytes received 69 bytes 294.00 bytes/sec total size is 0 speedup is 0.00
備份文件會是/tmp/back/baz.c,它不帶尾碼,反覆執行也依然是該文件。
--suffix=SUFFIX:指定備份文件的尾碼。預設的備份尾碼是“~”。
[root@C7 tmp]# rsync -vb --suffix=alongdidi /foo/bar/baz.c /tmp/ baz.c sent 78 bytes received 35 bytes 226.00 bytes/sec total size is 0 speedup is 0.00
備份文件是/tmp/baz.calongdidi,反覆執行的話也依然是該文件。
rsync的備份機制似乎不能遞增,只能反覆覆蓋,感覺並沒有什麼卵用。
-e, --rsh=COMMAND:用於選擇一個遠程shell程式,現在所使用的一般都是SSH了(以前是RSH,但是RSH沒有加密功能),所以一般是用於指定SSH的選項。
主要用於指定ssh的參數,以及用於臨時daemon。
-e 'ssh -p 2234' -e 'ssh -o "ProxyCommand nohup ssh firewall nc -w1 %h %p"'
--port=PORT:如果使用的rsync daemon的工作方式的時候,用於指定埠號,預設是873。
--password-file=FILE:用於指定rsync認證的密碼文件。非SSH認證的密碼。FILE可以為“-”表示讀取STDIN。如果密碼文件是全局可讀,或者以root用戶運行rsync但是密碼文件的ownership不是root的話,那麼rsync會退出。
--existing, --ignore-non-existing:告訴rsync,只更新目標文件中已存在的文件。
--ignore-existing:告訴rsync,只更新目標文件中不存在的文件。
創建了2個目錄,目錄結構如下。預設情況下,將a目錄同步至b目錄的話,除了會將a.txt加入文件列表中以外,還會將{1,2,3}.txt也加入文件列表中。
[root@C7 tmp]# tree {a,b} a ├── 1.txt ├── 2.txt ├── 3.txt └── a.txt b ├── 1.txt ├── 2.txt ├── 3.txt └── b.txt 0 directories, 8 files
如果我們只想同步接收端已存在的文件的話,則使用--existing選項。
[root@C7 tmp]# rsync -rv --existing a/ b/ sending incremental file list 1.txt 2.txt 3.txt sent 235 bytes received 73 bytes 616.00 bytes/sec total size is 0 speedup is 0.00
如果我們只想同步接收端不存在的文件的話,則使用--ignore-existing選項。
[root@C7 tmp]# rsync -rv --ignore-existing a/ b/ sending incremental file list a.txt sent 157 bytes received 35 bytes 384.00 bytes/sec total size is 0 speedup is 0.00
--existing選項可以和--ignore-existing選項結合使用,結合使用的情況下不會同步任何文件,一般用於配合--delete選項實現在不傳輸任何數據的情況下,僅刪除接收端的額外文件。
可以看一下單獨使用--delete和結合使用的區別。
[root@C7 tmp]# rsync -rv --delete a/ b/ sending incremental file list deleting b.txt 1.txt 2.txt 3.txt a.txt sent 274 bytes received 101 bytes 750.00 bytes/sec total size is 0 speedup is 0.00 [root@C7 tmp]# rsync -rv --existing --ignore-existing --delete a/ b/ sending incremental file list deleting b.txt sent 114 bytes received 21 bytes 270.00 bytes/sec total size is 0 speedup is 0.00
--remove-source-files:源文件如果同步成功,則將其刪除。
[root@C7 tmp]# tree {a,b} a ├── 1.txt ├── 2.txt ├── 3.txt └── a.txt b ├── 1.txt ├── 2.txt ├── 3.txt └── b.txt 0 directories, 8 files [root@C7 tmp]# rsync -rv --remove-source-files a/ b/ sending incremental file list 1.txt 2.txt 3.txt a.txt sent 274 bytes received 124 bytes 796.00 bytes/sec total size is 0 speedup is 0.00 [root@C7 tmp]# tree {a,b} a b ├── 1.txt ├── 2.txt ├── 3.txt ├── a.txt └── b.txt 0 directories, 5 files
rsync的include/exclude模式
--exclude=PATTERN:rsync通過該選項來排除所不需要同步的文件。它是--filter選項的一種簡寫形式。
一個--exclude選項只能排除一個模式,如果要排除多個模式的話,可以在命令行中書寫多次--exclude選項,或者將模式逐行寫入文件中,然後使用--exclude-from引用該模式文件。
簡單的示例如下。
[root@C7 tmp]# tree {a,b} a ├── 1.txt ├── 2.txt ├── 3.txt └── a.txt b ├── 1.txt ├── 2.txt └── 3.txt 0 directories, 7 files [root@C7 tmp]# rsync -rv --exclude=a.txt a/ b/ sending incremental file list 1.txt 2.txt 3.txt sent 215 bytes received 73 bytes 576.00 bytes/sec total size is 0 speedup is 0.00 [root@C7 tmp]# rsync -rv --exclude=a.txt a b/ sending incremental file list a/ a/1.txt a/2.txt a/3.txt sent 230 bytes received 77 bytes 614.00 bytes/sec total size is 0 speedup is 0.00
第二次同步的時候,如果不加--exclude選項,那麼會同步以下:
- a/
- a/1.txt
- a/2.txt
- a/3.txt
- a/a.txt
我們排除的模式是a.txt,模式沒有以“/”開頭或者結尾,那麼只要傳輸整個名稱中某個部分包含了a.txt,就會生效。因此,a/a.txt也被排除掉了。
排除的時候,模式的書寫其實是一個難點。在man手冊中有比較詳細的描述,涉及到
- 源文件如果是個目錄,那麼末尾是否帶上斜線。
- 是否使用相對目錄的選項--relative。
- 什麼是傳輸中的根目錄。
- 模式是否以“/”開頭。若是則涉及到錨定傳輸根的概念。
- 模式是否以“/”結尾。若是則判定為目錄。
- 模式是否是無限制(unqualified)的,例如“foo”或者上述的“a.txt”。無限制指的是沒有以“/”開頭或者結尾。若是則匹配的靈活度是很大的。
- 等等。
這個需要大家自行看一下man手冊以及自己反覆敲命令體驗一下,一般是帶上-avn選項來測試。
再來幾個示例,首先我們先看一下目錄a的層級結構。
[root@C7 tmp]# tree a/ a/ ├── 1.txt ├── 2.txt ├── 3.txt ├── a.txt ├── index.php └── public └── index.php 1 directory, 6 files
然後我們以測試的形式,同步a目錄至b目錄,註意此時同步的源目錄a的末尾帶上了斜線。首先我們看一下不帶排除選項的話,會同步哪些文件。
[root@C7 tmp]# rsync -avn a/ b/ sending incremental file list ./ 1.txt 2.txt 3.txt a.txt index.php public/ public/index.php sent 232 bytes received 41 bytes 546.00 bytes/sec total size is 0 speedup is 0.00 (DRY RUN)
源目錄帶上斜線,並且沒有-R選項,這時候就已經確定了傳輸根了。即這個示例中的傳輸根是a/下開始。而不是a目錄本身開始,更不是/tmp/a(案例中我的PWD目錄是/tmp)開始。
這時候我們排除無限制的index.php。
[root@C7 tmp]# rsync -avn --exclude=index.php a/ b/ sending incremental file list ./ 1.txt 2.txt 3.txt a.txt public/ sent 175 bytes received 35 bytes 420.00 bytes/sec total size is 0 speedup is 0.00 (DRY RUN)
無限制的匹配範圍很大,只要整棵樹/整個名稱中包含了模式,就會生效。因此index.php和public/index.php都會排除掉。
接下來我們來一個有限制的,排除掉傳輸根下的index.php。
[root@C7 tmp]# rsync -avn --exclude=/index.php a/ b/ sending incremental file list ./ 1.txt 2.txt 3.txt a.txt public/ public/index.php
排除模式不改變,通過修改源目錄末尾的斜線,從而改變了傳輸根,再來看看變化。
[root@C7 tmp]# rsync -avn --exclude=/index.php a b/ sending incremental file list a/ a/1.txt a/2.txt a/3.txt a/a.txt a/index.php a/public/ a/public/index.php sent 244 bytes received 42 bytes 572.00 bytes/sec total size is 0 speedup is 0.00 (DRY RUN)
這個時候想要再排除a目錄下的index.php,就得輸入--exclude=a/index.php或者--exclude=/a/index.php了。
如果模式末尾帶上斜線,則表示這個模式匹配到的,一定得是一個目錄。因為index.php不是目錄,所以不會被排除了。
[root@C7 tmp]# rsync -avn --exclude=index.php/ a/ b/ sending incremental file list ./ 1.txt 2.txt 3.txt a.txt index.php public/ public/index.php sent 232 bytes received 41 bytes 546.00 bytes/sec total size is 0 speedup is 0.00 (DRY RUN)
--exclude用於排除,而--include用於包含。當同一個文件,既被排除又被包含的時候,要看哪個選項放在前面。先遇到先生效。
[root@C7 tmp]# rsync -avn --exclude=index.php --include=index.php a/ b/ sending incremental file list ./ 1.txt 2.txt 3.txt a.txt public/ public/test.txt sent 201 bytes received 38 bytes 478.00 bytes/sec total size is 0 speedup is 0.00 (DRY RUN) [root@C7 tmp]# rsync -avn --include=index.php --exclude=index.php a/ b/ sending incremental file list ./ 1.txt 2.txt 3.txt a.txt index.php public/ public/index.php public/test.txt sent 261 bytes received 44 bytes 610.00 bytes/sec total size is 0 speedup is 0.00 (DRY RUN)
當include和exclude規則同時使用且使用了遞歸選項(-r或者-a)的時候,如果排除了某個文件的父目錄(或者爺爺目錄等更高層的目錄),那麼即便該文件被包含了並且include的規則放在最前面,該文件也仍然不會被同步。
[root@C7 tmp]# rsync -avn --include=public/index.php --exclude=public/ a/ b/ sending incremental file list ./ 1.txt 2.txt 3.txt a.txt index.php sent 162 bytes received 34 bytes 392.00 bytes/sec total size is 0 speedup is 0.00 (DRY RUN)
rsync的--delete選項
在選項與示例中我們已經解釋了--delete選項的作用,在上文--existing和--ignore-existing結合使用的示例中我們也初次使用了它。
根據工作方式,即可刪除本地主機上的文件,也可以刪除目標主機上的文件。如果以一個空目錄作為源文件的話,則會清空目標目錄。
當--delete選項和--exclude選項同時使用的時候,被排除的文件不會被刪除。我們來驗證一下。
文件層級結構如下。
[root@C7 tmp]# tree test{1,2} test1 ├── 1.txt ├── 2.txt └── 3.txt test2 ├── 1.txt ├── 2.txt ├── 3.txt ├── apple.jpg ├── icon.jpg ├── my.cnf ├── mysqld.log └── pear.jpg 0 directories, 11 files
僅刪除不排除的情況。
[root@C7 tmp]# rsync -rvn --delete test1/ test2/ sending incremental file list deleting pear.jpg deleting mysqld.log deleting my.cnf deleting icon.jpg del