Skip to content
VDS · 备份与磁盘

用 rsync 做备份

如何通过 SSH 将文件复制到另一台服务器、用硬链接建立版本历史,以及如何避免危险的 --delete 选项删除过多内容。

更新于 2026年8月23日

rsync 是最简单的可用复制方式:它随处可用,只传输文件中发生变化的部分,并且可以通过 SSH 工作。对于小型数据集来说,这已经足够了。

基本命令

rsync -avz --delete \
  -e "ssh -i /root/.ssh/backup_key -p 22" \
  /var/www/ backup@backup.example.com:/srv/backup/vds/www/

参数说明:

  • -a —— 保留权限、所有者、时间和链接;
  • -v —— 显示执行过程;
  • -z —— 传输时压缩(在带宽不超过 500 Mbps 且数据量很大时有用);
  • --delete —— 删除接收端上源端已不存在的文件。

源路径末尾的斜杠表示“目录的内容”;不带斜杠则复制目录本身。/var/www/ 和 /var/www 的结果不同,再配合 --delete,这种差异会删掉不该删的东西。请始终先用 --dry-run 试运行。

rsync -avzn --delete /var/www/ backup@backup.example.com:/srv/backup/vds/www/

-n 参数即试运行。

免密访问密钥

定时复制需要在不输入密码的情况下登录:

ssh-keygen -t ed25519 -f /root/.ssh/backup_key -N ""
ssh-copy-id -i /root/.ssh/backup_key.pub backup@backup.example.com

在接收端将此密钥限制为只能执行一条命令——这样即使密钥被盗,也无法获得 shell。在接收端的 ~/.ssh/authorized_keys 中:

command="rrsync -wo /srv/backup",restrict ssh-ed25519 AAAA... backup

使用硬链接保留版本历史

普通 rsync 只保留当前状态:如果您昨天删除了一个文件、今天才发现,就无处恢复。--link-dest 可以为您提供历史记录:未更改的文件不会被再次复制,而是建立链接,因此三十份副本占用的空间只比一份略多。

#!/bin/bash
set -euo pipefail
DEST=/srv/backup/vds
TODAY=$(date +%F)
rsync -a --delete \
  --link-dest="$DEST/latest" \
  /var/www/ "$DEST/$TODAY/"
ln -sfn "$DEST/$TODAY" "$DEST/latest"
find "$DEST" -maxdepth 1 -type d -mtime +30 -name "20*" -exec rm -rf {} +

请按计划在夜间运行脚本,并始终记录日志。

排除项

rsync -avz --exclude-from=/root/backup-exclude.txt / backup@host:/srv/backup/vds/root/
/proc/
/sys/
/dev/
/run/
/tmp/
/var/lib/docker/
/var/cache/
*.log

复制整个根目录很少有必要:更有用的是根据具体要备份什么一文构建一份精确的列表。

何时不适合使用 rsync

  • 如果您需要存储加密和去重,请使用 Restic。
  • 如果数据不断变化且完整性很重要,请先导出数据库,再对生成的文件执行 rsync。
  • 接收端是您不信任的他人存储:rsync 按原样写入文件,没有客户端加密。

常见错误

  • --delete 搭配了错误的源路径。 空的源目录会清空接收端。试运行是必须的。
  • 副本位于同一块磁盘上。 这不是备份,而是同一故障的第二个目标。请参阅异地副本。
  • 对已压缩的数据使用压缩。 -z 只会拖慢归档文件和镜像的传输。
  • 夜间任务遇到磁盘瓶颈。 写入吞吐量上限取决于套餐等级:请参阅磁盘速度。--bwlimit=20000 以及在非高峰时段运行会有所帮助。
  • 没有人检查结果。 请记录返回码并监控它:rsync ... || echo "backup failed" | mail -s alert you@example.com。