用 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 按原样写入文件,没有客户端加密。