备份与文件传输工具¶
主要作者
本文编写中
简介¶
备份是保障数据安全的重要手段。在理想情况下,备份应做到 3-2-1 原则:三份文件的副本,其中两份存储在不同的设备上,另一份远程存储。
一般来讲,管理员需要设置定时任务(使用 crontab 或者 systemd timer),在任务中调用备份数据的命令来实现备份。常见的方法包括:
- 使用
tar
归档数据目录。 - 使用
rsync
同步数据目录。 - 使用数据库的 dump 工具(例如
mysqldump
)备份数据库。 - 使用 Btrfs 或 ZFS 的快照与 send/receive 功能。
- 使用
rclone
同步到云存储(例如 OneDrive、S3 对象存储等)。 - 使用诸如 Duplicity、BorgBackup 等备份工具。
- 特定平台可能有专用的备份工具,例如虚拟化平台 Proxmox VE 的 Proxmox Backup Server。
单纯的快照与 RAID 都不是备份
快照是文件系统的特性,如果文件系统损坏,那么快照就都无法正常读取。而 RAID 只能在硬盘故障数量小于对应等级限制时才能保证数据完整性,无法防止在诸如误删除、自然灾害等情况下数据的丢失与损坏。
以下从上述方法列表引申开来,介绍一部分工具的使用方法与技巧。
Rsync¶
Rsync 是最常用的文件同步工具之一,支持本地复制和远程复制。相比于 cp
(本地)和 scp
(SSH 远程),rsync
可以做到增量复制,只复制文件中发生变化的部分,并且能够保留文件完整的元数据信息。Rsync 也是从镜像站点同步完整镜像的事实标准。
文件传输¶
最常用的命令:
参数含义如下:
参数 | 说明 |
---|---|
-a |
归档模式,等同于 -rlptgoD |
-r |
递归复制目录 |
-l |
保留符号链接 |
-p |
保留文件权限 |
-t |
保留修改时间(mtime) |
-g |
保留 group 信息 |
-o |
保留 owner 信息 |
-D |
保留设备文件与特殊文件 |
-v |
详细输出 |
-P |
保留传输一部分的文件且显示进度 |
--delete |
删除目标目录中源目录没有的文件 |
以下提供一些参考示例。
将 /A
文件复制到 /tmp/A
:
将 /etc
文件夹复制为/复制到 /tmp/example
。区别在 source 的结尾是否有 /
,如果没有的话,源文件夹就会作为一个整体复制到目标文件夹内;否则如果有 /
,源文件夹内的内容会被复制到目标文件夹内。
rsync -avP /etc /tmp/example1
# 此时 /etc/passwd 对应 /tmp/example1/etc/passwd
rsync -avP /etc/ /tmp/example2
# 此时 /etc/passwd 对应 /tmp/example2/passwd
作为 scp
的高效替代,rsync
也支持基于 SSH 的远程复制(远程服务器也需要安装 rsync)。可以使用 -z
开启压缩,以 CPU 为代价减小传输量。rsync
对增量复制的支持允许了「断点续传」的功能,在网络情况欠佳的时候尤其有用。
rsync -avPz user@remote:/path/to/source /path/to/destination
rsync -avPz /path/to/source user@remote:/path/to/destination
如果远程服务器需要特殊的 ssh
参数(例如端口),并且不想修改 ~/.ssh/config
,可以使用 -e
参数:
镜像同步¶
Rsync 同时也可以作为服务端(daemon 模式)对外提供 rsync 服务,默认端口为 TCP 873。
Rsync over TLS
Rsync 默认为明文协议,不过其支持通过其他反向代理工具(例如 Nginx 的 stream 模块)实现 TLS 加密,默认端口为 874,需要使用 rsync-ssl
命令连接。
以下介绍与镜像同步(mirrors)相关的服务端与客户端配置。其他用途可视情况自行调整。
Rsync 服务端配置¶
Debian 默认的 rsync 的 systemd 服务依赖于 /etc/rsyncd.conf
文件,同时 /usr/share/doc/rsync/examples/rsyncd.conf
提供了一个参考范例。
一份用于镜像站点的 rsyncd.conf
可能如下所示:
motd file = /etc/rsyncd/rsyncd.motd
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log
max verbosity = yes
transfer logging = yes
ignore nonreadable = yes
# 需要 adduser --system rsyncd
uid = rsyncd
gid = nogroup
use chroot = yes
dont compress = *
max connections = 50
refuse options = checksum
read only = true
timeout = 240
reverse lookup = no
其中比较重要的参数有:
- 安全性相关:rsync daemon 会以 root 身份运行,在收到请求后会 fork 出子进程实际处理请求。
uid
与gid
用于子进程降权,use chroot
用于限制访问范围,避免非预期的漏洞泄漏系统中的其他文件。由于镜像站点肯定不允许用户修改文件,因此read only
应当设置为true
。 - 性能相关:
max connections
用于限制总连接数,timeout
用于限制连接超时时间,防止被未响应的客户端长时间占用资源。dont compress
与refuse options
用于禁用压缩(如果需要传输的文件大多已经是压缩过的)与检验和(会大量占用服务器 CPU)。reverse lookup
用于关闭反向 DNS 查询,避免 DNS 问题导致的连接延迟。
之后就是定义暴露的模块(module):
模块是 rsync URL 的第一层,例如 rsync://server/repo1/somedir/
中,repo1
就是模块名。配置完成之后,可以使用 rsync://server/
列出全部模块,rsync rsync://server/repo1
来确认,并且采用类似的命令同步某个模块的全部文件。
同时启用多个 rsync 服务
如果有需要多个 daemon 的需求(例如需要多个 rsync 服务端 bind 到不同的 IP 地址上),可以使用 systemd 的模板单元格式手动编写 [email protected]
文件。
同时 rsyncd.conf
格式支持导入其他的配置文件,因此不同服务的共通部分可以提取出来。其中 &include
用于导入模块的定义,&merge
用于导入配置,类似如下:
使用 systemd 安全加固 rsync 服务
Systemd 服务的安全加固参数可以帮助避免未知的安全问题影响 rsync 服务,特别是在 rsync 于 2025 年 1 月暴露了多个 CVE 的情况下(其中两个是服务端的漏洞),这样的加固就显得更加重要。
一份参考 [email protected]
如下,其中包含安全加固以及降低 IO 与 CPU 优先级的设置(这同样也是科大镜像站目前使用的配置):
[Unit]
Description=fast remote file copy program daemon
ConditionPathExists=/etc/rsyncd/rsyncd-%i.conf
After=network.target network-online.target
[Service]
Type=exec
PIDFile=rsyncd-%i.pid
ExecStart=/usr/bin/rsync --daemon --no-detach --config=/etc/rsyncd/rsyncd-%i.conf
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7
IOAccounting=true
ProtectSystem=strict
ProtectHome=true
ProtectProc=invisible
ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=true
PrivateTmp=true
PrivateDevices=true
NoNewPrivileges=true
MemoryDenyWriteExecute=true
ReadWritePaths=/var/log/rsyncd
[Install]
WantedBy=multi-user.target
Alias=[email protected]
也可以考虑将 uid
与 gid
修改为在 systemd 服务中配置(而不是让 daemon 自己降权),并且提供 chroot
等必要的 capability。
Rsync 反向代理
ustclug/rsync-proxy 项目支持基于模块名的 rsync 反向代理,可以将不同的模块放在不同的服务器上,由 rsync-proxy 代理到不同的后端服务器上。
Rsync 客户端参数¶
一份参考的完整参数如下(修改自 ustcmirror-images 的 rsync 同步脚本):
rsync -pPrltvH --partial-dir=.rsync-partial --timeout 14400 --safe-links --delete-excluded --delete-delay --delay-updates --sparse --max-delete 4000 rsync://server/repo1/ /path/to/destination
其中部分参数含义如下:
参数 | 说明 |
---|---|
-H |
保留硬链接 |
--partial-dir |
保证部分传输的文件均在该目录中 |
--timeout |
超时时间 |
--safe-links |
忽略指向对应仓库外部的符号链接,避免有问题的符号链接导致其他文件非预期暴露 |
--delete-excluded |
删除被排除(exclude)的文件 |
--delete-delay |
在同步完成后再删除文件,避免在同步过程中删除文件导致仓库不可用 |
--delay-updates |
在同步完成后再更新文件,避免在同步过程中更新文件导致仓库不可用 |
--sparse |
保留稀疏文件的稀疏性 |
--max-delete |
限制删除文件的数量,避免误操作导致大量文件被删除 |
包含与排除¶
Rsync 支持 --include
与 --exclude
参数。简单来讲,rsync 的处理规则如下:
- 每个文件/文件夹会按照用户在命令行中提供的顺序匹配,如果命中,则会被处理,后续的规则对该文件不再生效。
- 如果没有命中任何规则,那么会被包含。
- 命中
--exclude
代表其子文件和文件夹也会被排除,因此如果要包含a/b/c/d
,那么a/
,a/b/
,a/b/c/
都需要被包含。
文件备份¶
Rsync 本身不是完整的备份工具,其没有版本管理功能,因此如果某个文件被误删除/修改,那么 rsync 会将这个变化同步到备份中。不过基于 rsync 高效复制文件的能力,有工具实现了基于 rsync 和文件系统硬链接功能的备份,例如 Linux Mint 的 Timeshift 项目就通过硬链接实现不同时间点备份的去重操作,而 rsync 负责文件的复制。