本篇介紹如何使用 Linux 的 rsync 同步與備份各種檔案,自動製作快照式累進備份。

rsync 是 Linux 系統上最常被用來複製與備份檔案的工具,它可以處理本機或遠端的檔案同步工作,藉由 rsync 指令可以讓管理者很方便的將兩地的資料同步,不管是同一台電腦或是透過網際網路連線的兩台伺服器,使用方式都類似,以下是 rsync 的使用教學以及常用的指令範例。

rsync 簡介

rsync 的角色就像是一般 Linux 的 cpscp 指令,可以將檔案或目錄從來源位置複製到目的位置,不過 rsync 在複製檔案時會比 cpscp 更有效率,並且支援連結檔與設備檔(devices),也可以保留檔案的擁有者、群組與權限設定,

rsync 在第一次複製檔案時,會複製完整的檔案內容,而之後再次複製檔案時,就會先以 delta transfer 演算法檢查新舊檔案之間的差異,只傳送有變動的部份,可加快備份速度,尤其是在累進備份大檔案時,效果更明顯。另外 rsync 在使用網路傳送資料時,也支援資料的自動壓縮與解壓縮,這樣可以有效減少耗費的網路頻寬。

安裝 rsync

大部分的 Linux 發行版都會內建 rsync 工具,如果您的系統沒有安裝,通常也都可以透過系統的套件來安裝。Red Hat 系列的 Linux 可用 yum 安裝:

sudo yum install rsync

Debian 系列的 Linux 則可用 apt-get

sudo apt-get install rsync

rsync 基本用法

rsync 的基本語法結構如下:

rsync 參數 來源檔案 目的檔案

以下是最常見的幾個參數:

  • -v:verbose 模式,輸出比較詳細的訊息。
  • -r:遞迴(recursive)備份所有子目錄下的目錄與檔案。
  • -a:封裝備份模式,相當於 -rlptgoD,遞迴備份所有子目錄下的目錄與檔案,保留連結檔、檔案的擁有者、群組、權限以及時間戳記。
  • -z:啟用壓縮。
  • -h:將數字以比較容易閱讀的格式輸出。

rsync 最簡單的用法就是複製本地端的檔案:

rsync -avh myfile.gz /home/pi/tmp/
sending incremental file list
myfile.gz

sent 14.34M bytes  received 35 bytes  28.67M bytes/sec
total size is 14.33M  speedup is 1.00

其效果就跟 cp -r 類似,可將 myfile.gz 複製到 /home/pi/tmp/ 目錄中,不過如果執行第二次時,rsync 就會自動跳過沒有變動的檔案:

rsync -avh myfile.gz /home/pi/tmp/
sending incremental file list

sent 74 bytes  received 12 bytes  172.00 bytes/sec
total size is 14.33M  speedup is 166,658.15

這種用法對於檔案或目錄都適用:

rsync -avh /path/to/myfolder /home/pi/tmp/

rsync 遠端備份

rsync 也可以用於不同台機器之間的遠端備份,這樣的用法就跟 scp 指令很像,不過 rsync 會更有效率:

rsync -avzh /mypath/myfile.gz pi@192.168.1.12:/mybackup/

這樣就會將本地端的 myfile.gz 備份至 pi@192.168.1.12/mybackup/ 目錄中,在遇到這種遠端備份的狀況時,rsync 預設會以 ssh 的方式登入遠端的機器,所以在執行這行備份指令之後,要接著輸入pi@192.168.1.12 的密碼,接著就會開始備份資料,輸出會類似這樣:

pi@192.168.1.12's password: 
sending incremental file list
myfile.gz

sent 13.62M bytes  received 34 bytes  48.56K bytes/sec
total size is 14.33M  speedup is 1.05

而這裡我們多加入一個 -z 參數,目的是讓 rsync 可以自動將資料壓縮後再傳送,並在遠端接收到資料後自動解壓縮,減少網路傳輸的資料量。

rsync 也可以將遠端的檔案備份至本地端,其語法也跟 scp 類似:

rsync -avzh pi@192.168.1.12:/mypath/myfile.gz /mybackup/
pi@192.168.1.12's password: 
receiving incremental file list
myfile.gz

sent 30 bytes  received 23.74M bytes  571.98K bytes/sec
total size is 24.14M  speedup is 1.02

這裡的 rsync 在複製檔案時,由於我們加入了 -a 參數,所以可以用於檔案或是整個目錄的備份,相當於 scp -r 的效果,而且由於 rsync 只會傳輸有變動的部份,所以通常在異地備份資料時都會使用這種方式來處理。

限制網路頻寬

如果不想讓 rsync 在透過網路備份資料時,佔用太大的網路頻寬而影響正常的服務,可以加上 --bwlimit 參數來指定資料傳輸的速度上限:

rsync -avzh --bwlimit=100K pi@192.168.1.12:/mypath/myfile.gz /mybackup/
pi@192.168.1.12's password: 
receiving incremental file list
myfile.gz

sent 30 bytes  received 14.34M bytes  99.22K bytes/sec
total size is 14.33M  speedup is 1.00

自訂 SSH 連接埠

正常 ssh 遠端登入服務的連接埠(port)號碼是 22,但有些人為了保護伺服器避免受到太多的網路攻擊,會將 ssh 的連接埠改成其他的號碼,例如 12345,不過這樣的話在使用 rsync 進行遠端備份資料時,就也要跟著指定連接埠號碼。

假設 192.168.1.12 這台伺服器的 ssh 服務連接埠號碼為 12345,以下是透過 rsync 將資料備份資料的範例:

rsync -avzh -e 'ssh -p 12345' /mypath/myfile.gz pi@192.168.1.12:/mybackup/

這裡我們多加入一個 -e 參數,其用途是指定遠端登入所要使用的指令,預設的指令就是 ssh,而這裡我們將指令變更為 ssh -p 12345,也就是使用 12345 這個連接埠登入 ssh 的意思(請參考 ssh 指令的 -p 參數用法)。

顯示傳輸進度

如果要讓 rsync 在傳輸檔案時可以即時顯示進度,可以加上 --progress 參數:

rsync -avzh --progress pi@192.168.1.12:/mypath/myfile.gz /mybackup/

這樣在備份每的檔案的過程就會顯示傳輸的進度、傳輸速度與剩餘時間等資訊:

pi@192.168.1.12's password: 
receiving incremental file list
myfile.gz
         24.14M 100%  623.52kB/s    0:00:37 (xfr#1, to-chk=0/1)

sent 30 bytes  received 23.74M bytes  558.52K bytes/sec
total size is 24.14M  speedup is 1.02

同步刪除檔案

rsync 預設只會將來源端現存的檔案同步更新至目的端(同步所有新增或修改的檔案),但是如果在來源端有檔案被刪除的話,rsync 並不會主動刪除目的端的檔案,這樣可以確保資料被勿刪時,備份檔不會也跟著被刪除。

如果您想要讓 rsync 也同步將不存在於來源端的檔案刪除的話,可以加上 --delete 參數,如果沒有來源檔案只有新增、沒有減少的話,它就跟一般的複製動作相同:

rsync -avh --delete myfolder/ backup/
sending incremental file list
./
data1.txt
data2.txt
data3.txt
data4.txt

sent 432 bytes  received 95 bytes  1.05K bytes/sec
total size is 116  speedup is 0.22

這時候若我們將來源檔案的 data1.txtdata2.txt 刪除,並且增加 data5.txt,在執行一次 rsync

rsync -avh --delete myfolder/ backup/
sending incremental file list
deleting data2.txt
deleting data1.txt
./
data5.txt

sent 190 bytes  received 64 bytes  508.00 bytes/sec
total size is 87  speedup is 0.34

這時候 rsync 就會同步將備份端的 data1.txtdata2.txt 刪除,並且同時新增 data5.txt

如果這裡我們沒有加上 --delete 參數的話,rsync 就只會新增 data5.txt,不會刪除任何檔案。

備份特定檔案

假設我們的檔案與目錄結構如下:

tree myfolder
myfolder
├── chinese.py
├── data1.txt
├── data2.txt
├── find_edimax.c
└── src
    ├── pack.c
    ├── test1.txt
    └── test2.txt

若要讓 rsync 在備份檔案時,排除所有 *.txt 的文字檔檔案,可以使用 --exclude 參數:

rsync -avh --exclude '*.txt' myfolder/ backup/
sending incremental file list
./
chinese.py
find_edimax.c
src/
src/pack.c

sent 3.91K bytes  received 88 bytes  7.99K bytes/sec
total size is 3.59K  speedup is 0.90

我們可以使用多個 --exclude 來排除多種檔案,例如:

rsync -avh --exclude '*.txt' --exclude '*.py' myfolder/ backup/
sending incremental file list
./
find_edimax.c
src/
src/pack.c

sent 3.74K bytes  received 65 bytes  7.61K bytes/sec
total size is 3.50K  speedup is 0.92

如果只想要備份某些特定的檔案,可以將 --exclude--include 配合使用,例如只備份所有 *.c 的 C 語言原始碼:

rsync -avh --include '*.c' --include '*/' --exclude '*' myfolder/ backup/
sending incremental file list
./
find_edimax.c
src/
src/pack.c

sent 3.74K bytes  received 69 bytes  7.62K bytes/sec
total size is 3.50K  speedup is 0.92

這裡我們加入兩個 --include 來指定要備份的檔案比對規則,*.c 就是包含所有 C 語言的原始碼檔案,而另外一個 */ 的意思是指包含所有的目錄,若沒有加上包含目錄的參數,所有的目錄就會被後面 --exclude 排除,造成所有子目錄中的 *.c 也跟著被排除。最後加上一個 --exclude 排除其餘所有的檔案,請注意 --exclude 要放在 --include 之後,順序不可以對調。