服务器硬盘坏掉的那一刻,你手里有没有一份能直接恢复的备份,答案只取决于两件事:有没有一个定时任务在跑,以及那个任务用的命令对不对。rsync 是 Linux 世界里这个问题的标准答案——Ubuntu 24.04 自带 3.2.7 版本,apt 安装即可,一条命令就能完成增量同步。本文从它的同步机制讲起,覆盖日常备份必需的选项组合、两个最常见的翻车点,最后给出一个用硬链接实现的多版本快照脚本。
它凭什么快:两步算法,只传差量
rsync 的核心能力是增量传输:第一次全量复制,之后每次只传有变化的部分。判断「有没有变」分两步走。
第一步是文件级筛选。rsync 先对源和目标各建一份文件清单,比较每个文件的大小和修改时间(mtime),两者都一致的文件直接跳过,一个字节都不传。这一步决定了大多数日常备份只花几秒钟——因为绝大多数文件根本没动过。
第二步是块级比对,只对「清单显示有变化」的文件生效。rsync 把文件切成固定大小的块,对每一块计算校验和,两端比对后只传输不一致的块。对一个大文件中间改了几 KB 的场景,这条规则能把传输量压到总大小的零头。数据库文件、虚拟机镜像这类「永远在变但变化很小」的大文件,是块级差量最大的受益者。
顺带一提,rsync 也能当 cp 的替代品:rsync -P 源 目标(等价于 --partial --progress)在复制大文件时保留半成品并显示进度条,中断后重跑同一命令,已经传完的部分不会重传。跨文件系统搬大目录时,这一点比 cp 舒服得多。
结尾斜杠:rsync 第一个坑就在语法里
rsync 对源路径末尾的 / 有特殊语义,这是它和 cp 行为不同的地方,也是新手事故的高发区:
# 带斜杠:把 source 目录「里面的内容」同步到 dest 下,dest 本身就是 source 的镜像
rsync -a /var/www/ /backup/www/
# 不带斜杠:把 source「整个目录」放进 dest,生成 /backup/www/source/...
rsync -a /var/www /backup/www/
man page 的原话是:末尾斜杠「就像拷贝目录内容,而非目录本身」(“the contents of the directories, not the directory itself”)。另一条相关规则:目标目录不存在时 rsync 会自动创建,只创建最后一层,父目录必须提前存在。
习惯建议只有一条:目标路径末尾统一加斜杠(/backup/www/),源路径写完先确认一遍。要么在所有命令里统一带斜杠,要么统一不带——混用才是事故来源。
日常备份:一套标准选项组合
rsync 选项极多,日常备份常用的组合:
rsync -aAXv --delete --exclude={'/proc/*','/sys/*','/tmp/*','/cache/*'} /path/to/source/ /path/to/dest/
关键选项拆开看:
| 选项 | 作用 | 备份场景里的意义 |
|---|---|---|
-a | 归档模式,等价 -rlptgoD:递归 + 保留符号链接、权限、修改时间、属组、属主、设备文件 | 元数据不丢,恢复出来就能直接用 |
-A | 保留 ACL 扩展权限 | Web 目录常给运行用户加 ACL,丢了会出诡异权限问题 |
-X | 保留扩展属性(xattr) | SELinux/AppArmor 标签、capabilities 靠它 |
-v | 显示同步明细 | 排查用,cron 里可以去掉 |
-h --info=progress2 | 人类可读单位 + 总进度条 | 手动跑大目录时加,观察整体百分比 |
--exclude | 排除匹配的路径 | 缓存、临时文件没必要进备份 |
-x | 不跨文件系统边界 | 源目录下挂了别的盘时,防止把挂载点内容也灌进去 |
--delete 必须单独拎出来讲:它让目标端删除源端已经不存在的文件,保持两边严格镜像。 生产备份用它前先想清楚——源端误删,下一次同步会把误删原样复制到备份端,你连「从备份里捞回来」的机会都没有。做法有两种:要么备份脚本不用 --delete,接受目标端残留已删文件(多占空间但保命);要么用下面快照方案,误删只影响当前这一个快照点。同理,--backup --backup-dir=目录 会把被覆盖/删除的文件挪进指定目录而不是直接抹掉,需要留后路时可以加上。
快照式备份:—link-dest 让每天一份全量只花一份的钱
理想的备份要能回到上周三,rsync 的 --link-dest 用硬链接实现这个效果,思路类似苹果 Time Machine:每次备份生成一个独立的时间点目录,没变化的文件是硬链接——硬链接指向同样的数据块,不占新空间,真正复制的只有变过的文件。30 天的备份,磁盘占用接近一份全量加 30 天的增量。
Ubuntu 24.04 的 rsync 3.2.7 已内置 --mkpath,目标多级目录不存在时自动创建,脚本不用再手动 mkdir -p。
#!/bin/bash
# /usr/local/bin/snapshot-backup.sh —— 每天一个快照点,保留 14 天
set -euo pipefail
SRC="/var/www/" # 源路径,结尾斜杠语义见上文
SNAP_ROOT="/backup/snapshots" # 快照根目录
TODAY=$(date +%F)
LAST="${SNAP_ROOT}/last" # 指向上一个快照的软链接
rsync -aAX --delete --link-dest="$LAST" "$SRC" "${SNAP_ROOT}/${TODAY}/"
# 更新软链接,供下一次快照做硬链接基准
ln -sfn "${SNAP_ROOT}/${TODAY}" "$LAST"
# 清理 14 天前的快照目录
find "$SNAP_ROOT" -maxdepth 1 -type d -name '20*' -mtime +14 -exec rm -rf {} +
第一次运行时 last 链接还不存在,rsync 会退回全量复制,正好当基准。验证快照的完整性和空间占用:
diff -r /var/www/ /backup/snapshots/$(date +%F)/ # 无输出 = 内容一致
du -sh /backup/snapshots/2026-10-08 # 远小于源目录即硬链接生效
异机备份:SSH 通道 + timer 自动化
备份数据和服务器放同一块盘,盘坏了一起走。异机备份让 rsync 走 SSH 通道,源机执行:
rsync -aAX --delete -e ssh /var/www/ [email protected]:/srv/backup/www/
前提是两台机器都装了 rsync。自动化的关键在 SSH 密钥:给备份专门生成一对密钥,公钥追加到目标机的 authorized_keys,确认 ssh -i 专用私钥 [email protected] 免密可登录后,配一个 systemd timer 每天执行:
# /etc/systemd/system/backup.service
[Unit]
Description=Daily rsync backup to remote host
[Service]
Type=oneshot
ExecStart=/usr/bin/rsync -aAX --delete -e "ssh -i /root/.ssh/backup_ed25519" /var/www/ [email protected]:/srv/backup/www/
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 03:30
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now backup.timer
systemctl list-timers backup.timer # 确认下次触发时间
Persistent=true 保证凌晨关机错过的备份在开机后补跑。定时任务配置的取舍在另一篇 timer 详解里展开过,这里只补一点:备份脚本务必加 -i 显式指定密钥,防止 root 的默认密钥被其他任务占用后备份静默改走密码认证然后卡死。
权限注意:-a 要保留属主信息,而普通用户无权改属主,所以目标端常需要 root 权限。规范做法是给 SSH 登录加 from="源机IP," 限制 + 命令白名单,或者用 rsync 自带的 rrsync 脚本把该密钥限制在备份目录内——开放 root 免密但不限制来源,等于把目标机钥匙插在门上。
常见问题
Q:rsync 和 cp 有什么区别,小文件多的目录该用谁? cp 是无脑全量复制,每次都传全部内容。rsync 先比对清单,没变的文件直接跳过。文件数量大但变化少的目录,rsync 第二次同步通常几秒结束。文件数量达到几十万级时,清单比对本身也要吃时间,可以给两者计时再决定。
Q:目标目录不存在会自动创建吗?
会,但只创建最后一层。/backup/2026/10/08/ 这类多级路径,3.2.7 之前的版本要提前 mkdir -p,3.2.7 之后可以直接加 --mkpath。
Q:—delete 到底该不该用? 取决于备份策略。单目录镜像同步(比如网站静态文件发布)用它是刚需;容灾备份建议不用,改用上面的快照方案——每个时间点独立,误删只污染当天快照。
Q:怎么确认备份真的可用?
定期抽查恢复。最简单的是 diff -r 源目录 备份目录,无输出即一致。更进一步是每隔几周把备份恢复到一个临时目录,实际把服务跑起来——验证「能恢复」而不是「文件在」。
Q:同步中途断网/断电,数据会不会坏?
rsync 传到一半的文件默认丢弃并重来,加 --partial 可以保留半成品、下次续传。快照脚本里的 --delete 配合 --link-dest 使用时,中断的快照目录删除后重跑即可,不影响已完成的历史快照。
结语
rsync 的价值在于把「备份」从一个手动负担变成一行 cron/timer 配置。最小可行方案三件事:异机或异盘存放、SSH 密钥自动化、硬链接快照保留多版本。跑通之后每个季度做一次恢复演练——备份的可靠性从来由恢复成功那一刻定义,不由脚本定时执行定义。