rsync
rsync 是一个开源实用程序,提供快速增量文件传输。
安装
rsync 必须安装在源主机和目标主机上。
前端
- Grsync — GTK 前端。
- luckyBackup — Qt 前端,使用 C++ 编写。
- nbRsync — 用于 rsync 的 JavaFX GUI,带有集成的计划程序。
其他使用 rsync 的工具包括 rdiff-backupAUR、 osyncAUR 和 yarsyncAUR。
作为 cp/mv 的替代方案
rsync
可以用作 cp
或 mv
命令的高级替代方案,尤其是在复制较大的文件时
$ 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
显示 verbosity 级别为 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 使用 SSHremoteuser
: 是主机remotehost
上的用户-a
: 将所有这些选项分组-rlptgoD
(recursive, links, perms, times, group, owner, devices)
-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
recursive, links, perms, times, group, owner, devices--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
),但扩展名为 .service
而不是 .path
(在本例中为 backup.service
)。
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 RULES 和 rsync(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
。
SOURCE_DIR
的末尾包含尾部斜杠,原因如 #尾部斜杠注意事项 中所述。生成的副本可以在文件系统级别使用 diff
的递归选项简单地重新读取和检查(例如,在数据恢复尝试之后)
diff -r SOURCE_DIR DESTINATION_DIR
可以通过使用本文中描述的 rsync 并更新 fstab 和 引导加载程序 来成功进行文件系统迁移,如 将安装迁移到新硬件 中所述。这本质上提供了一种将任何根文件系统转换为另一个文件系统的方法。
作为守护进程
rsync 可以作为 守护进程 在服务器上运行,监听 TCP 端口 873
。
编辑模板 /etc/rsyncd.conf
,配置共享并启动 rsyncd.service
。
rsyncd.service
和 rsyncd@.service
。已注释掉 ProtectHome
的更改,[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/***
参见
- 更多用法示例可以在 社区贡献 和 通用编程 论坛中搜索
- Howto – 使用硬链接进行本地和远程快照备份的 rsync 包括使用硬链接的文件重复数据删除、MD5 完整性签名、“chattr”保护、过滤规则、磁盘配额、具有指数分布的保留策略(备份轮换,同时保存比旧备份更新的备份)
- 将 SSH 密钥/身份文件与 rsync 一起使用