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 的主要目的是远程复制文件,即在两个不同的主机之间复制。远程位置可以使用 host-colon 语法指定

$ 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,progress2stats1 以详细级别 1 显示 rsync 传输统计信息。 progress2 打印总传输进度,而不是每个文件的传输进度 (progress1)
  • --modify-window=1:在比较两个文件的时间戳时,如果它们的时间戳之差小于 1 秒,则将它们的时间戳视为等效
  • --remove-source-files:在文件成功同步后,从源目录中删除文件
注意: 术语校验和的使用与 --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[@]}"

此脚本可以放在路径中的某个位置,并在 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、硬链接或扩展属性,例如 capabilities)
  • --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#使用 NetworkManager 调度器的网络服务)。

使用 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),但扩展名为 .service 而不是 .path(在本例中为 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 中的模式(每行一个)匹配的文件/目录,类似于 #高级过滤规则用法 中描述的示例,但不包含 +/- 语法。

目录 /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 命令,但源和目标反转。

高级过滤规则用法

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 选项。这可以从文本文件中获取输入,其中包含目录或文件路径的列表,每个条目以换行符分隔。应该注意的是,即使已经包含 -a,如果用户想要递归目录复制,也必须为此选项手动指定 -r 标志。

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

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

文件系统克隆

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

rsync 的归档模式几乎可以胜任这项工作,但它不备份特殊的文件系统元数据,例如访问控制列表、扩展属性或稀疏文件属性。为了在文件系统级别成功克隆,需要提供一些额外的选项

rsync -qaHAXS SOURCE_DIR DESTINATION_DIR

它们的含义是(来自手册页)

--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 的末尾包含尾部斜杠,原因如 #尾部斜杠注意事项 中所述。

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

diff -r SOURCE_DIR DESTINATION_DIR

通过使用本文中描述的 rsync 并更新 fstab启动引导器,如 迁移安装到新硬件 中所述,可以成功进行文件系统迁移。这本质上提供了一种将任何根文件系统转换为另一个文件系统的方法。

作为守护进程

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/***

参见