rsync

出自 Arch Linux 中文维基

rsync 是一個開源工具,可以進行快速的增量文件傳輸。

安裝[編輯 | 編輯原始碼]

安裝 rsync 軟件包。

必須在源計算機和目標計算機上都安裝 rsync

前端[編輯 | 編輯原始碼]

  • Grsync — GTK 前端。
https://www.opbyte.it/grsync/ || grsync
  • JotaSync — 用於 rsync 的 Java Swing GUI,內置計劃功能。
https://trixon.se/projects/jotasync/ || jotasyncAUR
  • luckyBackup — 用 C++ 編寫的 Qt 前端。
https://luckybackup.sourceforge.net/index.html || luckybackupAUR

其他使用 rsync 的工具是 rdiff-backup, osyncAURyarsyncAUR

作為 cp/mv 的替代[編輯 | 編輯原始碼]

注意: 在不同的文件系統之間使用 rsync 而不是 cp/mv 是高效的,但對於在同一個文件系統上複製或移動文件卻不然。參見 [1]

rsync 可以作為 cpmv 命令的高級替代品,特別是對於較大文件的複製:

$ rsync -P source destination

其中 -P--partial --progress 選項的作用是相同的,該選項使得文件可以分塊傳輸並顯示傳輸過程中的進度。

您可能需要使用 -r/--recursive 選項遞歸到目錄中傳輸。

可以像 cp 命令一樣本地複製文件,但 rsync 令人激動的用途在於遠程複製文件,例如在兩個不同的主機之間。遠程位置可以用主機加冒號進行指定:

$ rsync source host:destination

或者

$ rsync host:source destination

網絡文件傳輸默認使用SSH協議,host 可以是真實的主機名或來自於 .ssh/config 的預先定義的配置文件/別名。

無論是本地或遠程文件傳輸,rsync 首先會創建一個文件列表,其中含有接下來會被用於確定各個文件是否需要構建的信息(默認為文件大小和上次修改時間戳)。對於每個需要構建的文件,都會找出其所有塊(長度S字節,不重疊,偏移量可由S整除)的一個弱校驗和和一個強校驗和。使用這一信息,一個大文件就可以由 rsync 構建,而無需傳輸整個文件。更詳細的實際解釋和詳細的數學解釋見 rsync 如何工作rsync 算法

要快速使用合理默認值,可以使用一些別名:

cpr() {
  rsync --archive -hh --partial --info=stats1,progress2 --modify-window=1 "$@"
} 
mvr() {
  rsync --archive -hh --partial --info=stats1,progress2 --modify-window=1 --remove-source-files "$@"
}
  • -hh: 以人類可讀的格式輸出數字
  • --info=stats1,progress2: stats1 使用詳細級別1顯示 rsync 傳輸統計信息。progress2 打印總的傳輸進度,而不是每個文件的傳輸進度(progress1)
  • --modify-window=1: 當比較兩個文件的時間戳時,如果時間戳的差異小於1秒,則將它們的時間戳視為相等
  • --remove-source-files: 成功同步後從源目錄中刪除文件
注意: 此處對校驗和這一名詞的使用與 --checksum 選項的行為不是相等價的。--checksum 選項影響的是在傳輸任何文件之前使用的決定是否跳過文件的啟發式方法。在基於塊的文件構建中一定會使用校驗和,這是 rsync 傳輸文件的方法,與 --checksum 無關。

注意尾隨下劃[編輯 | 編輯原始碼]

Arch 默認使用 GNU cp (coreutils 的一部分)。 然而,rsync 遵循 BSD cp 的約定, 源目錄後面帶有一個斜槓「/」有着特定的處理。比如:

$ rsync -r source destination

創建一個有着 "source"內容的 "destination/source"目錄,命令:

$ rsync -r source/ destination

把"source/"目錄下的所有文件全部複製到"destination"目錄下,而沒有中間的子目錄 - 就像你調用了:

$ rsync -r source/. destination

這與 GNU cp 的行為是不同的,在 GNU cp 中"source" 與 "source/" 意義相同 ("source/."則不然)。並且,一些shell在Tab補全目錄名的時候自動追加尾部下劃線。由於這些因素,新手或偶爾使用 rsync 的用戶可能傾向於忘記 rsync 的不同行為,在命令行上留下了結尾的下劃線,從而無意間造成混亂,甚至覆蓋重要文件。

謹慎起見,可以使用包裝腳本在調用 rsync 之前自動刪除尾部斜槓:

#!/bin/bash
new_args=()
for i in "${@}"; do
    case "${i}" in
        /)
            i="/"
        ;;
        */)
            i="${i%/}"
        ;;
        esac
    new_args+=("${i}")
done
exec rsync "${new_args[@]}"

該腳本可以放在 path 中的某個位置,並在 shell 的 init 文件中指定別名為 rsync。

作為備份工具[編輯 | 編輯原始碼]

rsync 協議可以很容易地用於備份,只傳輸自上次備份以來已更改的文件。本節將介紹一些簡單的基於 rsync 的計劃備份腳本,通常用於複製到可移動介質。

自動備份[編輯 | 編輯原始碼]

以下面的腳本為例,該腳本放置於 /etc/cron.daily 目錄下,如果 cron 守護程序 被正確安裝和配置,它將每天運行。配置和使用 cron 是本文的範圍之外。

首先,創建一個包含相應命令選項的腳本:

/etc/cron.daily/backup
#!/bin/sh
rsync -a --delete --quiet /path/to/backup /location/of/backup
-a
表示文件應被存檔,這意味着他們的大部分特性被保留 (包括 ACLs, 硬鏈接或擴展屬性,如 capabilities)
--delete
指同步源的刪除操作。

在這裡,/path/to/backup 應該改成需要被備份的路徑 (比如 /home),/location/to/backup 是備份應存放的位置 (比如 /media/disk).

最後,腳本必須可執行

通過 SSH 自動備份[編輯 | 編輯原始碼]

如果是通過 SSH 備份到遠程主機,改為使用此腳本:

/etc/cron.daily/backup
#!/bin/sh
rsync -a --delete --quiet -e ssh /path/to/backup remoteuser@remotehost:/location/of/backup
-e ssh
告訴rsync的使用SSH
remoteuser
遠程主機 remotehost 上的用戶名
-a
組中的所有這些選項 -rlptgoD (recursive, links, perms, times, group, owner, devices)
注意: 在每次增量備份的時候,Rsync 都會試着修改目標主機上所有先前備份過的文件以匹配源主機上的文件狀態。這意味着在通過 SSH (並且使用 -a選項保留權限和所有者的時候)備份屬於 root 的文件,需要目標主機的 root 權限。通常的辦法是將 SSH 守護程序設置為允許使用公玥而不是密碼登錄,並以 root 用戶運行 rsync 命令。

使用 NetworkManager 自動備份[編輯 | 編輯原始碼]

該腳本在網絡連接後開始備份。

首先,創建一個包含相應命令選項的腳本:

/etc/NetworkManager/dispatcher.d/backup
#!/bin/sh

if [ x"$2" = "xup" ] ; then
        rsync --force --ignore-errors -a --delete --bwlimit=2000 --files-from=files.rsync /path/to/backup /location/of/backup
fi
-a
組中的所有選項 -rlptgoD recursive, links, perms, times, group, owner, devices
--files-from
從文件中讀取到備份路徑/path/to/backup的相對路徑
--bwlimit
限 I/O 帶寬;每秒千字節

這個腳本必須屬於 root 用戶 (參見 NetworkManager#使用 NetworkManager 調度網絡服務 )。

使用 systemd 和 inotify 自動備份[編輯 | 編輯原始碼]

注意:
  • 由於 inotify 和 systemd 的限制, (見 這個問題和回答),遞歸的文件系統監測是不可能的。即使你監測了一個目錄和它的內容,它也不會遞歸子目錄並檢測其中的內容。你必須明確地指出所有需要檢測的目錄,就算這些目錄是你已經監視的目錄的子目錄。
  • 以下設置基於一個 systemd/用戶 的實例。

相比於執行一個基於時間計劃的定時備份,比如使用 cron,在每次文件變動的時候都執行備份也是可行的。systemd.path 單元使用 inotify 以監測文件系統,並且可以與 systemd.service 文件一同使用來在捕獲到文件系統事件的時候啟動任何進程(如你的 rsync 備份)。

首先,創建監測備份文件的 systemd.path 文件:

~/.config/systemd/user/backup.path
[Unit]
Description=Checks if paths that are currently being backed up have changed

[Path]
PathChanged=%h/documents
PathChanged=%h/music

[Install]
WantedBy=default.target

然後創建一個 systemd.service 文件,它將會在檢測到變化的時候啟動。默認情況下一個與 .path 單元同名(本例中為 backup.path),但以 .service 結尾的服務(本例中為 backup.service)將會啟動。

注意: 如果你需要運行多個 rsync 命令,使用 Type=oneshot。這將允許你指定多個 ExecStart= 參數,每個參數對應一個 rsync 命令。更簡單的方法是寫一個腳本來啟動你所有的備份,就像 cron 腳本一樣。
~/.config/systemd/user/backup.service
[Unit]
Description=Backs up files

[Service]
ExecStart=/usr/bin/rsync %h/./documents %h/./music -CERrltm --delete ubuntu:

現在只需要像普通的 systemd 服務那樣,啟動/啟用 backup.path 它就會開始監測文件變化並且自動啟動 backup.service 了。

每周差異備份[編輯 | 編輯原始碼]

這個 rsync 選項很有用,每次運行時創建一個完整備份,並且每天在一個單獨的目錄中保留已修改文件的差異備份副本。

首先,創建一個包含相應命令選項的腳本:

/etc/cron.daily/backup
#!/bin/sh

DAY=$(date +%A)

if [ -e /location/to/backup/incr/$DAY ] ; then
  rm -fr /location/to/backup/incr/$DAY
fi

rsync -a --delete --quiet --inplace --backup --backup-dir=/location/to/backup/incr/$DAY /path/to/backup/ /location/to/backup/full/

--inplace 選項包含 --partial ,就地更新目標文件。

快照備份[編輯 | 編輯原始碼]

同樣你也可以用這個工具來創建你文件的快照樹(即一個有日期順序的文件副本的目錄)。這個快照樹是基於硬鏈接的,這意味着只有修改過的文件才會占用空間。這也是蘋果 TimeMachine 的原理。

實現這個功能的腳本很容易實現,使用 --link-dest 選項來創建增量快照,硬鏈接未改變的文件:

/usr/local/bin/snapbackup.sh
#!/bin/sh

# 基本的快照式 rsync 备份脚本

# 配置
OPT="-aPh"
LINK="--link-dest=/snapshots/username/last/" 
SRC="/home/username/files/"
SNAP="/snapshots/username/"
LAST="/snapshots/username/last"
date=`date "+%Y-%b-%d:_%T"`

# 运行 rsync 以创建快照
rsync $OPT $LINK $SRC ${SNAP}$date

# 删除指向上一个快照的符号链接
rm -f $LAST

# 创建到最新快照的新符号链接,以便下次备份到硬链接
ln -s ${SNAP}$date $LAST

這裡必須有一個指向完整備份的符號鏈接,以作為 --link-dest 的目標。如果最近的快照被刪除,那麼就需要重新創建一個指向新的快照的符號鏈接。如果 --link-dest 沒有找到有效的符號鏈接,rsync將繼續複製所有文件,而不只複製變化。

一個更加複雜一點的版本每次保留一個最新的完整備份到 $SNAP/latest 。若自上次完整備份起有一定數量的文件發生了變化,那麼腳本將創建一個新的快照到 $SNAP/$DATETAG ,並使用 cp -al 來硬鏈接未改變的文件:

/usr/local/bin/rsnapshot.sh
#!/bin/sh

## 我自己的基于 rsync 的快照式备份过程
## (cc) marcio rps AT gmail.com

# 配置变量

SRC="/home/username/files/" #dont forget trailing slash!
SNAP="/snapshots/username"
OPTS="-rltgoi --delay-updates --delete --chmod=a-w"
MINCHANGES=20

# 以低优先级运行此进程

ionice -c 3 -p $$
renice +12  -p $$

# 同步

rsync $OPTS $SRC $SNAP/latest >> $SNAP/rsync.log

# 检查是否有足够的变化,如果有
# 则制作一份以日期命名的硬链接副本

COUNT=$( wc -l $SNAP/rsync.log|cut -d" " -f1 )
if [ $COUNT -gt $MINCHANGES ] ; then
        DATETAG=$(date +%Y-%m-%d)
        if [ ! -e $SNAP/$DATETAG ] ; then
                cp -al $SNAP/latest $SNAP/$DATETAG
                chmod u+w $SNAP/$DATETAG
                mv $SNAP/rsync.log $SNAP/$DATETAG
               chmod u-w $SNAP/$DATETAG
         fi
fi


懶得手動運行的話,你也可以讓這個腳本作為 systemd/定時器 單元運行。

全盤系統備份 [編輯 | 編輯原始碼]

本節介紹使用rsync傳輸整個/樹的副本,不包括一些選定的目錄。這種方法被認為比使用dd進行磁盤克隆更好,因為它允許使用不同的大小、分區表和文件系統,也比使用cp-a進行複製更好,因為其允許對文件權限、屬性、訪問控制列表和擴展屬性進行更大的控制。 本節是關於使用 rsync 來創建一份整個 / 樹的副本,其中不包含特定的幾個文件夾。此方法相較於使用 dd 來進行硬盤克隆要更佳,因為它允許你在使用不同大小、分區表和文件系統的存儲設備間傳輸;也比 cp -a 更好,因為它允許你對文件權限、屬性、訪問控制列表擴展屬性有更好的掌握。

rsync 在系統運行時亦可進行備份,但傳輸期間改變的文件可能不會被備份。這可能會造成使用這些文件的程序的一些未知錯誤或未定義行為。

這種方法對於將現有的已安裝系統遷移到新的硬盤或固態硬盤上非常有效。

在 root 權限下運行此命令,以確保 rsync 能訪問到所有系統文件,並且保留權限:

# rsync -aAXHv --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} / /path/to/backup

通過使用 -aAX 選項集,文件以歸檔模式傳輸,確保符號鏈接、設備、權限、所有權、修改時間、ACLs和擴展屬性得以保留,前提是目標文件系統支持這一功能。選項 -H 保留了硬鏈接,但會使用更多的內存。

--exclude 選項使符合給定模式的文件被排除。在上述命令中,/dev/proc/sys/tmp/run 等目錄被包括在內,但這些目錄的內容被排除在外。這是因為它們在系統啟動時才會被填入內容,但這些目錄本身不會被創建。 /lost+found 是針對文件系統的。上面的命令依賴於 bashzsh 中可用的括號擴展。當使用不同的 shell 時,應該手動重複 --exclude 模式。加入排除選項可以避免被 shell 誤擴展,例如,在通過 SSH 備份時,這是必要的。以 * 結尾的排除路徑可以確保目錄本身在不存在的情況下被創建。

注意:
  • 如果計劃將系統備份到 /mnt/media 以外的其他位置,請不要忘記將其添加到排除的模式列表中,以避免無限循環。
  • 如果系統中有任何綁定掛載,也應排除它們,以便綁定掛載的內容只複製一次。
  • 如果使用交換文件,請確保也將其排除在外。
  • 考慮是否要備份 /home/ 目錄。如果它包含您的數據,它可能比系統大得多。另外,請考慮排除不重要的子目錄,例如 /home/*/.thumbnails/*, /home/*/.cache/mozilla/*, /home/*/.cache/chromium/*, 和 /home/*/.local/share/Trash/*,具體取決於系統上安裝的軟件。
  • 如果安裝了 GVFS,則必須排除 /home/*/.gvfs,以防止 rsync 錯誤。
  • 如果安裝了 Dhcpcd ≥ 9.0.0,請排除 /var/lib/dhcpcd/* 目錄,因為它將多個系統目錄作為子目錄掛載在那裡。

您可能希望包括其他 rsync 選項,或刪除一些選項,例如以下選項。有關完整列表,請見 rsync(1)

  • 如果您在內存非常低的系統上運行,請考慮刪除 -H 選項;然而,這在大多數現代機器上應該沒有問題。文件系統上可能有許多硬鏈接,具體取決於使用的軟件(例如,如果您使用 Flatpak)。許多硬鏈接位於 /usr/ 目錄下。
  • 如果在同一備份目錄中多次運行 rsync,則可能需要添加 rsync 的 --delete 選項。在這種情況下,請確保源路徑不以 /* 結尾,否則此選項將僅對源目錄子目錄中的文件有效,但對直接駐留在源目錄內的文件無效。
  • 如果您使用任何稀疏文件,如虛擬磁盤、Docker 映像和類似文件,則應添加 -S 選項。
  • --numeric-ids 選項將禁止映射到用戶名和組名;相反,數字的組和用戶 ID 將被直接傳輸。這在通過 SSH 進行備份或使用 live 系統備份不同的系統盤時非常有用。
  • 選擇 --info=progress2 選項而不是 -v 選項將顯示整體進度信息和傳輸速度,而不是正在傳輸的文件列表。
  • 為了避免在遞歸時跨越文件系統邊界,請添加選項 -x/--one-file-system。這將防止備份層次結構中的任何掛載點。

還原備份[編輯 | 編輯原始碼]

如果希望還原備份,請使用執行的 rsync 命令,但源和目標相反。

篩選規則的高級用法[編輯 | 編輯原始碼]

rsync 可以從單個過濾器文件中讀取所有這些規則,而不是單獨指定包含和排除規則。rsync 以自頂向下的順序處理規則;首先匹配的規則獲勝。

backup.filter
# 排除的模式

- .thumbnails/***
- node_modules/***
- venv/***

# 包含的模式

+ /Documents/***
+ /Books/***
+ /Music/***

# 排除其他所有內容
- /**

*** 是一種特殊的 rsync 模式,它遞歸地匹配文件夾及其所有內容。

查看 rsync(1) § PATTERN MATCHING RULESrsync(1) § FILTER RULES IN DEPTH 獲取更多詳情。

然後用此命令運行 rsync:

$ rsync -aAXHv --filter="merge backup.filter" $SRC $DEST

關鍵字是 --filter "merge ..." 參數,它將獲取過濾器文件並按順序解析每個同步文件的規則。

文件系統克隆[編輯 | 編輯原始碼]

rsync 提供了一種複製文件系統中所有數據的方法,同時保留儘可能多的信息,包括文件系統元數據。這是一個文件系統級別的數據克隆過程,其中源文件系統和目標文件系統不需要是同一類型。它可以用於備份、文件系統遷移或數據恢復。

rsync 的 歸檔 模式接近於適合該工作,但它不備份特殊的文件系統元數據,例如訪問控制列表、擴展屬性或稀疏文件財產。為了在文件系統級別成功克隆,需要提供一些其他選項:

rsync -qaHAXS SOURCE_DIR DESTINATION_DIR

它們的意思是(來自手冊頁):

--hard-links, -H        保留硬链接
--acls, -A              保留 ACLs(包含 --perms)
--xattrs, -X            保留扩展属性
--sparse, -S            将空序列转换为稀疏块

此外,如果要從副本中排除樹下掛載的其他文件系統,請使用 -x

注意: 如果您正在使用 rsync 將 Arch 安裝遷移到新驅動器,請記住在 SOURCE_DIR 末尾添加一個尾隨斜槓,原因在#注意尾隨下劃中提到。

可以使用 diff 的遞歸選項在文件系統級別簡單地重新讀取和檢查生成的副本(例如,在數據恢復嘗試之後):

diff -r SOURCE_DIR DESTINATION_DIR

通過使用 rsync(如本文所述)和更新 fstab引導加載程序(如遷移到新硬件中所述),可以成功執行文件系統遷移。這本質上提供了一種將任何根文件系統轉換為另一個文件系統的方法。

作為守護程序[編輯 | 編輯原始碼]

rsync 可以在偵聽端口 873 的服務器上作為守護程序運行。

編輯模板 /etc/rsyncd.conf,配置共享並啟動 rsyncd.service

注意: 截至 rsync 3.2.0-1,該軟件包採用了上游 systemd 單元文件 rsyncd.servicersyncd@.serviceProtectHome 的更改已被注釋,[Service] 節下的安全功能 ProtectSystem=full 仍處於活動狀態。這將使 /boot/, /etc//usr/ 目錄只讀。如果您需要 rsyncd 寫入系統目錄,您可以編輯該單元,並在重寫代碼段的 [Service] 節中設置 ProtectSystem=off

來自客戶端使用,例如列出服務器內容:

$ rsync rsync://server/share

將文件從客戶端傳輸到服務器:

$ rsync local-file rsync://server/share/

考慮在 iptables 打開端口 873 和用戶身份驗證。

注意: 包括用戶身份驗證在內的所有傳輸數據均未加密。

示例配置[編輯 | 編輯原始碼]

從文件列表共享[編輯 | 編輯原始碼]

/etc/rsyncd.conf
...

# 跨越文件系統邊界時需要。
#use chroot  = no
read only = yes

...

[sync]
    path         = /
# 要複製的文件列表。
    include from = /backup.list
# 排除其餘部分。
    exclude      = *

在文件列表中,所有 中間路徑 都是必需的,除非使用 *** 通配符:

/backup.list
/etc/
/etc/conf.d/
/etc/conf.d/hwclock
/etc/fonts/***

另見[編輯 | 編輯原始碼]