跳转至内容

rsync

来自 ArchWiki

rsync 是一款开源实用程序,可提供快速的增量文件传输。

安装

安装 rsync 包。

rsync 必须安装在源机器和目标机器上。

前端

  • Grsync — GTK 前端。
https://www.opbyte.it/grsync/ || grsync
  • luckyBackup — 使用 C++ 编写的 Qt 前端。
https://luckybackup.sourceforge.net/index.html || luckybackupAUR
  • nbRsync — 带集成计划程序的 rsync 的 JavaFX GUI。
https://trixon.se/projects/nbrsync/ || 未打包? 在 AUR 中搜索

其他使用 rsync 的工具有 rdiff-backupAURosyncAURyarsyncAUR

作为 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 可以构造一个大文件,而无需传输整个文件。有关更详细的实际和数学解释,请分别参考 how rsync worksthe rsync algorithm

为了快速使用合理的默认设置,您可以使用一些别名。

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,progress2stats1 显示 rsync 传输统计信息,详细程度为 1。progress2 打印总传输进度,而不是逐文件传输进度(progress1)。
  • --modify-window=1:在比较两个文件的最后修改时间时,如果它们的最后修改时间相差小于 1 秒,则认为它们的时间戳等效。
  • --remove-source-files:成功同步文件后,从源目录中删除文件。
注意 "checksum"(校验和)一词的使用**不**与 --checksum 选项的行为互换。--checksum 选项影响在传输任何文件之前使用的文件跳过启发式。独立于 --checksum,校验和始终用于基于块的文件构造,这就是 rsync 传输文件的方式。

末尾斜杠注意事项

Arch 默认使用 GNU cp(GNU coreutils 的一部分)。然而,rsync 遵循 BSD cp 的约定,该约定对带有末尾斜杠 "/" 的源目录给予特殊处理。而

$ rsync -r source destination

会创建一个名为 "destination/source" 的目录,其中包含 "source" 的内容,命令

$ rsync -r source/ destination

会将 "source/" 中的所有文件直接复制到 "destination" 中,中间没有子目录——就像您调用它时一样

$ rsync -r source/. destination

此行为与 GNU cp 不同,GNU cp 将 "source" 和 "source/" 视为相同(但 "source/." 除外)。此外,一些 shell 在选项卡补全目录名时会自动附加末尾的斜杠。由于这些因素,新用户或偶尔使用的 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 启动文件中将其别名为 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:表示文件应被存档,意味着其大部分特性被保留(但**不**包括 ACL、硬链接或功能等扩展属性)。
  • --delete:表示源文件上删除的文件也将在备份中被删除。

在此,/path/to/backup 应更改为需要备份的内容(例如 /home),而 /location/of/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(递归、链接、权限、时间、组、所有者、设备)。
注意 rsync 会尝试修改目标机器上任何先前备份的文件,以匹配它们在源机器上的当前状态,每次增量备份时都会如此。这意味着当通过 SSH 备份由 root 拥有的文件时(以及使用 -a 选项保留权限和所有权时),需要对目标机器的 root 访问权限。实现此目的以实现自动化的首选方法是设置 SSH 守护进程,允许 root 使用公钥无密码登录,并以 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 递归、链接、权限、时间、组、所有者、设备。
  • --files-from:从该文件读取 /path/to/backup 的相对路径。
  • --bwlimit:限制 I/O 带宽;每秒千字节数。

脚本必须由 root 拥有(有关详细信息,请参见 NetworkManager#Network services with NetworkManager dispatcher)。

通过 systemd 和 inotify 进行自动化备份

  • 由于 inotify 和 systemd 的限制(参见 此问答),无法进行递归文件系统监视。尽管您可以监视目录及其内容,但它不会递归进入子目录并监视其内容;您必须显式指定每个要监视的目录,即使该目录是已监视目录的子目录。
  • 此设置基于 systemd/User 实例。

与使用基于时间的计划(例如 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 文件,该文件将在检测到更改时被激活。默认情况下,与路径单元(在此例中为 backup.path)同名的服务文件将被激活,只是扩展名从 .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 并原地更新目标文件。

快照备份

同样的想法可用于维护文件的快照树。换句话说,一个包含按日期排序的文件副本的目录。副本使用硬链接制作,这意味着只有更改的文件才会占用空间。总的来说,这就是 Apple 的 TimeMachine 背后的理念。

这个基本脚本易于实现,并使用 --link-dest 选项通过硬链接未更改的文件来创建快速的增量快照。

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

# Basic snapshot-style rsync backup script 

# Config
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"`

# Run rsync to create snapshot
rsync $OPT $LINK $SRC ${SNAP}$date

# Remove symlink to previous snapshot
rm -f $LAST

# Create new symlink to latest snapshot for the next backup to hardlink
ln -s ${SNAP}$date $LAST

必须存在一个指向完整备份的符号链接作为 --link-dest 的目标。如果删除了最新的快照,则需要重新创建符号链接以指向最新的快照。如果 --link-dest 未找到有效的符号链接,rsync 将继续复制所有源文件,而不是仅复制更改的文件。

一个更复杂的版本会维护一个最新的完整备份 $SNAP/latest,并且如果自上次完整备份以来更改的文件数量达到一定程度,它将使用 cp -al 创建当前完整备份的快照 $SNAP/$DATETAG,以硬链接未更改的文件。

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

## my own rsync-based snapshot-style backup procedure
## (cc) marcio rps AT gmail.com

# config vars

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

# run this process with real low priority

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

# sync

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

# check if enough has changed and if so
# make a hardlinked copy named as the date

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/Timers 单元运行。

完整系统备份

本节介绍了使用 rsync 传输整个 / 目录树的副本,并排除一些选定的目录。这种方法比使用 dd 进行磁盘克隆要好,因为它允许使用不同的大小、分区表和文件系统,并且比使用 cp -a 复制要好,因为它允许更精确地控制文件权限、属性、访问控制列表扩展属性

rsync 即使在系统运行时也能工作,但在传输过程中更改的文件可能已被传输,也可能未被传输,这可能导致使用已传输文件的某些程序出现未定义行为。为缓解此问题,请注销所有用户并关闭所有程序和数据库。

这种方法非常适合将现有安装迁移到新的硬盘或 SSD

以 root 身份运行以下命令,以确保 rsync 可以访问所有系统文件并保留所有权。

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

通过使用 -aAX 选项集,文件以存档模式传输,这确保了符号链接、设备、权限、所有权、修改时间、ACL 和扩展属性被保留,前提是目标 文件系统支持该功能。-H 选项保留硬链接,但会消耗更多内存。

--exclude 选项会导致匹配给定模式的文件/目录被排除。代替或结合使用,--exclude-from=file 选项排除匹配 file 中模式(每行一个)的文件/目录,类似于 #Advanced usage of filter rules 中描述的示例,但没有 +/- 语法。

以上命令包含 /dev/proc/sys/tmp/run 目录,但排除了这些目录的*内容*。这是因为它们是在启动时填充的,但目录本身并未创建。/lost+found 是文件系统特定的。引用排除模式将避免被 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 的 --delete 选项。在这种情况下,请确保源路径不以 /* 结尾,否则此选项只会影响源目录子目录内的文件,而对直接位于源目录内的文件无效。
  • 如果您使用任何稀疏文件,例如虚拟磁盘、Docker 镜像等,您应该添加 -S 选项。
  • --numeric-ids 选项将禁用用户和组名的映射;相反,将传输数字用户和组 ID。这在通过 SSH 进行备份或使用实时系统备份不同系统磁盘时很有用。
  • 选择 --info=progress2 选项而不是 -v 将显示整体进度信息和传输速度,而不是正在传输的文件列表。
  • 为避免在递归时跨越文件系统边界,请添加 -x/--one-file-system 选项。这将防止备份层次结构中的任何挂载点。

恢复备份

如果您想恢复备份,请使用与执行相同的 rsync 命令,但将源和目标反转(您可能还想在源路径末尾添加斜杠)。如果您使用了 --exclude 选项,那么在恢复命令中应该删除它们。

高级过滤器规则用法

rsync 可以从单个过滤器文件中读取所有包含和排除规则,而不是单独指定它们。rsync 按从上到下的顺序处理规则;第一个匹配的规则生效。

backup.filter
# Exclude patterns

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

# Include patterns

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

# Exclude everything else
- /**

*** 是一个特殊的 rsync 模式,它可以递归地匹配一个文件夹及其所有内容。

请参阅 rsync(1) § PATTERN MATCHING RULESrsync(1) § FILTER RULES IN DEPTH 以获取更多详细信息。

然后使用以下命令运行 rsync:

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

关键是 --filter "merge ..." 参数,它将读取过滤器文件并按顺序解析每个同步文件的规则。

从路径列表中复制

--files-from 选项是 #Advanced usage of filter rules 方法的替代方案。它可以从包含目录或文件路径列表的文本文件中获取输入,每个条目由换行符分隔。需要注意的是,如果用户想要递归目录复制,即使已经包含 -a,也必须为该选项手动指定 -r 标志。

例如,可以使用以下命令归档目录列表及其所有递归目录:

$ rsync -aAXHvr --files-from="dir_list.txt" $SRC $DEST

文件系统克隆

rsync 提供了一种方法来复制文件系统中的所有数据,同时尽可能多地保留信息,包括文件系统元数据。这是一个文件系统级别的数据克隆过程,源和目标文件系统不必是同一类型。它可以用于备份、文件系统迁移或数据恢复。

rsync 的*存档*模式非常适合这项工作,但它不会备份特殊文件系统元数据,例如访问控制列表、扩展属性或稀疏文件属性。要成功进行文件系统级别的克隆,需要提供一些额外的选项。

rsync -qaHAXS SOURCE_DIR DESTINATION_DIR

它们的含义(来自 manpage)是:

--hard-links, -H         preserve hard links
--acls, -A               preserve ACLs (implies --perms)
--xattrs, -X             preserve extended attributes
--sparse, -S             turn sequences of nulls into sparse blocks

此外,如果要在要从复制中排除的树下挂载了其他文件系统,请使用 -x

注意 如果您使用 rsync 将 Arch 安装迁移到新驱动器,请记住在 SOURCE_DIR 末尾包含一个斜杠,原因如 #Trailing slash caveat 中所述。

可以使用 diff 的递归选项在文件系统级别简单地重新读取和检查生成的副本(例如,在数据恢复尝试后)。

diff -r SOURCE_DIR DESTINATION_DIR

可以通过按照本文档的描述使用 rsync 并更新 fstab引导加载程序(如 Migrate installation to new hardware 中所述)来实现成功的文件系统迁移。这本质上提供了一种将任何根文件系统转换为另一种文件系统的方法。

作为守护进程

rsync 可以作为 守护进程在服务器上运行,监听 TCP 端口 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/

考虑在 防火墙中打开 TCP 端口 873,并使用用户身份验证。

注意 所有传输的数据,包括用户身份验证,均未加密。

示例配置

从文件列表中共享

/etc/rsyncd.conf
...

# Needed when crossing filesystem boundaries.
#use chroot  = no
read only = yes

...

[sync]
    path         = /
# List of files to copy.
    include from = /backup.list
# Exclude the rest.
    exclude      = *

在文件列表中,所有*中间路径*都是必需的,除非使用了 *** 通配符。

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

参见