暗色模式

rsync 数据同步与备份实战:从增量原理到定时快照

技术教程
2026-08-04
11
0

说到 Linux 下的数据同步与备份,rsync 是绕不开的名字。无论是把网站文件同步到另一台服务器、给数据库目录做增量备份,还是搭建一套「时光机」式多版本快照,rsync 都是运维工具箱里的标配。它既有 cp 的简单直觉,又有 scp 的跨机器能力,更关键的是——它只传输有变化的部分,海量数据也能秒级完成增量同步。

这篇文章在 Ubuntu 24.04 服务器上把所有命令真实执行验证了一遍(rsync 3.2.7),从增量原理讲到定时备份实战,附终端实测截图,可以直接照着抄。

rsync 是什么:为什么备份都选它

rsync 是一个文件同步工具,核心特性就一句话:增量传输。它会把源端和目标端的文件逐个比对,只有真正发生变化(或新增)的文件才会被传输,未变化的文件直接跳过。

相比 scp/cp,rsync 的优势:

  • 增量同步:重复执行只传差异部分,重复备份的成本几乎为零
  • 断点续传--partial 保留已传一半的文件,中断后重跑即可续传
  • 保留属性-a 归档模式保留权限、属主、时间戳、软链接等元数据
  • 本地/远程通吃:同一套命令语法,既同步本机目录,也通过 SSH 跨主机同步
  • 网络友好--bwlimit 限速,-z 压缩,不把带宽吃满
  • 安全:走 SSH 加密通道,不需要额外开放端口(rsync 守护进程模式除外)

版本现状:rsync 最新稳定版是 3.3.0(2024 年 4 月发布,以 bug 修复和兼容性改进为主),Ubuntu 24.04 软件源自带 3.2.7(协议版本 31),日常使用完全够用,无需手工编译升级。

安装与版本确认

Ubuntu/Debian 一条命令装好:

sudo apt update && sudo apt install -y rsync

装完确认版本:

rsync --version | head -3
# rsync  version 3.2.7  protocol version 31
# Copyright (C) 1996-2022 by Andrew Tridgell, Wayne Davison, and others.

核心原理:增量同步是怎么省时间的

rsync 的增量算法是它的灵魂。传输前,发送端把每个文件切分成固定大小的块(默认约 700 字节到 1MB,视文件大小而定),先对每一块计算弱校验和(滚动校验和,可快速滚动计算),再对变化的块计算强校验和(MD5/SHA 等)。接收端对目标文件做同样的分块校验,只有校验值不匹配的块才会被传输,然后接收端把新块拼装到对应位置。

对一个只改了中间几个字节的大文件(比如数据库文件、日志文件),rsync 只需传几个块,而不是整个文件——这就是它能「秒同步」的原因。

不过要注意:rsync 默认的「快检」逻辑是大小 + 修改时间比对,只要大小和 mtime 一致就认为文件没变,不会做块级校验(块级校验很费 CPU)。如果你觉得有文件被漏掉,可以加 -c/--checksum 强制做校验和比对,代价是两边都要读一遍文件。

基础用法:本地目录同步

最常用的同步命令长这样(下文截图就是在 Ubuntu 24.04 上的真实输出):

rsync -avhP /var/www/site/ /backup/site/

解释一下这四个基础参数:-a 归档模式(递归 + 保留权限/属主/时间戳/软链接),-v 输出详细信息,-h 人类可读的容量显示,-P 等于 --partial(断点续传)+ --progress(显示进度)。

首次同步与再次同步的增量对比

注意截图里的两个细节:

  1. 首次同步时,每个文件都显示进度(8.39M 100% 569.20MB/s),最后一行 total size is 8.39M speedup is 1.00 表示全量传输;
  2. 再次运行完全相同的命令,输出只有一行统计:sent 225 bytes received 14 bytes ... speedup is 35,098.96——所有文件都没变化,一条数据都没传。这就是增量同步的直观体验:备份脚本重复跑再多次,代价都趋近于零。

常用参数速查

参数作用
-a归档模式:递归 + 保留权限、属主、时间戳、软链接
-v显示详细输出(文件名、统计)
-h容量以人类可读格式显示(M/G)
-P--partial(断点续传)+ --progress(进度条)
-n / --dry-run演练模式:只显示会做什么,不实际执行
-z传输前压缩(慢速网络收益明显,局域网反而拖慢速度)
--delete删除目标端多余的文件(镜像同步,慎用)
--exclude排除匹配模式的文件/目录
--bwlimit=5000限速 5000 KB/s,避免占满带宽
--link-dest=DIR与 DIR 中未变化的文件做硬链接,实现快照备份
-e "ssh -p 2222"指定远程传输通道(如自定义 SSH 端口)

最容易踩的坑:尾部斜杠

rsync 最经典、最容易翻车的坑:源目录尾部有没有斜杠,含义完全不同

  • rsync -av src /dest/ —— 拷贝目录本身,目标变成 /dest/src/...
  • rsync -av src/ /dest/ —— 拷贝目录的内容,目标直接是 /dest/...

下面这张截图用 --dry-run 做了对照实验(不会真的写入文件),效果一目了然:

源目录尾部斜杠的差异对比

不带斜杠时,文件列表顶部出现 src/,整个目录被原样放进目标;带斜杠时列表顶部是 ./,只有目录内容被同步。

记忆口诀:斜杠 = 只看内容。目标端尾部写不写斜杠通常无所谓,但源端一定要按你的意图写对。特别提醒:写定时备份脚本时,漏写源斜杠会导致目标目录多套一层,配合 --delete 时还可能误删不该删的目录树。

镜像同步:--delete 与 --exclude

备份场景里经常需要「目标完全等于源」:源端删掉的文件,目标端也要删。此时加 --delete,rsync 会把目标端多余的(源端没有的)文件删掉,实现镜像同步。

--delete 是危险参数——误删没有后悔药,所以实战铁律是--dry-run 演练,确认无误再真跑。下面截图演示了镜像同步的完整流程:先在目标端放一个多余的 old-unused.dat,再用 --delete --exclude "*.tmp" 同步:

镜像同步:--delete 与 --exclude 实测

三个关键信息:

  1. dry-run 输出 deleting old-unused.dat——明确指出将删除哪个文件,此时什么都不会发生;
  2. *.tmp--exclude 排除后,临时文件既不会被传输,也不会被删除(排除规则对双向都生效),同步是幂等的;
  3. 实际执行后 find 验证,目标端只剩与源端一致的文件,且 .tmp 安然无恙。

完整命令:

# 先演练
rsync -avn --delete --exclude "*.tmp" /var/www/site/ /backup/site/
# 确认无误后真跑
rsync -a --delete --exclude "*.tmp" /var/www/site/ /backup/site/

远程同步:基于 SSH

rsync 最常用的远程场景是走 SSH 通道,源和目标任意一侧写 user@host:path 即可:

# 本机 → 远端
rsync -avz /var/www/site/ root@192.168.1.10:/backup/site/
# 远端 → 本机
rsync -avz root@192.168.1.10:/var/www/site/ /backup/site/

几点实战经验:

  • 务必先配置 SSH 密钥免密登录,否则定时任务里无法自动执行(交互式输密码会卡死脚本);密钥配置方法见文末相关阅读里的 SSH 加固一文;
  • 自定义 SSH 端口时用 -e 指定:rsync -avz -e "ssh -p 2222" ...
  • 局域网内同步别加 -z,压缩反而浪费 CPU;跨机房慢速链路加 -z 收益明显;
  • 远程路径里含空格/特殊字符时,用引号包起来;
  • 基于 SSH 的同步复用 SSH 的权限体系,不要为了省事去开 rsync 守护进程模式rsync:// 协议,873 端口)——它需要单独管理密码文件,且默认无加密,多一个端口就多一个攻击面。如果确实要用守护进程模式,记得在防火墙放行 873 端口,见文末相关阅读的防火墙一文。

实战:定时增量备份

每日定时备份

把备份命令写成脚本,配合 cron 每天凌晨执行:

#!/bin/bash
# /usr/local/bin/backup-site.sh
SRC="/var/www/site/"
DST="/backup/site/$(date +%F)/"
mkdir -p "$DST"
rsync -a --delete --bwlimit=5000 "$SRC" "$DST"

再写入 crontab(每天凌晨 2:30 执行):

30 2 * * * /usr/local/bin/backup-site.sh >> /var/log/backup-site.log 2>&1

如果已经在用 systemd,用 timer 替代 cron 还能拿到失败重试、日志统一管理等能力,详见文末相关阅读的 systemd 一文。

多版本快照:--link-dest 硬链接技巧

只留一份「最新镜像」的风险是:误删文件、被勒索病毒加密后,备份也一并中招。更稳妥的做法是保留多份历史快照。rsync 的 --link-dest 参数就是为此设计的:与上一份快照未变化的文件用硬链接共享磁盘空间,每份新快照只占用实际变化数据的空间,历史版本却完整可回滚。

# 第一次全量快照
rsync -a /var/www/site/ /backup/snap/backup-v1/
# 之后每次用 --link-dest 指向上一份
rsync -a --link-dest=/backup/snap/backup-v1 /var/www/site/ /backup/snap/backup-v2/

上面这段脚本在我测试机上的实测结果:第一份快照占用 8.1M,第二份快照因为只改了一个小文件,实际只多占 16K——未变化的 big.dat 等文件通过硬链接与第一份共享同一个磁盘块。两份快照目录看起来都是完整文件,随时可以任意回滚。

注意两个细节:--link-dest 必须指向真实目录(传符号链接会报 --link-dest arg does not exist);--link-dest 参数写绝对路径最稳妥。结合 cron 可以轻松扩展成「每天一份快照、滚动保留最近 30 份」的经典备份方案:

#!/bin/bash
# /usr/local/bin/snapshot-daily.sh
DAY=$(date +%F)
rsync -a --link-dest=/backup/snap/backup-$(date -d yesterday +%F) \
  /var/www/site/ /backup/snap/backup-$DAY/
# 只保留最近 30 份
find /backup/snap -maxdepth 1 -type d -name "backup-*" | sort | head -n -30 | xargs -r rm -rf

常见场景速查

场景命令
目录内容同步到备份目录rsync -avhP src/ dst/
增量再跑一遍(验证一致性)重复执行相同命令即可
演练/预览将要同步什么rsync -avn src/ dst/
镜像同步(目标完全等于源)rsync -a --delete src/ dst/
排除日志与临时文件rsync -a --exclude "*.log" --exclude "cache/" src/ dst/
跨主机同步(走 SSH)rsync -avz src/ user@host:/dst/
自定义 SSH 端口rsync -avz -e "ssh -p 2222" src/ user@host:/dst/
备份时限速 5MB/srsync -a --bwlimit=5000 src/ dst/
多版本快照rsync -a --link-dest=上一份快照 src/ 新快照/
同步后删除源端文件(移动)rsync -a --remove-source-files src/ dst/

总结

  • rsync 的核心是增量传输:默认按「大小 + mtime」快速比对,-c 强制校验和比对;
  • 最常用的组合是 rsync -avhP,危险操作(--delete)先加 -n 演练;
  • 源目录尾部斜杠决定「拷贝目录本身还是内容」,写脚本时最容易出错;
  • 远程同步走 SSH 通道最安全,配好密钥免密即可自动定时执行;
  • --link-dest 硬链接快照是保留多版本备份的利器,成本几乎为零;
  • 最新稳定版为 3.3.0,Ubuntu 24.04 自带 3.2.7,功能足够日常使用。

参考资料

发表评论

暂无评论,快来抢沙发吧!