Linux灾备脚本核心是增量同步、定时触发与异地容错,依托rsync、shell和cron/systemd实现:一用-aAXv--delete+exclude构建基础备份;二以--link-dest+硬链接快照节省空间;三通过cron定时或systemd关机前执行;四借SSH免密实现异地同步。

Linux 中用 rsync 编写自动化灾备脚本,核心是“增量同步 + 定时触发 + 异地容错”。不靠复杂工具,只用系统自带的 rsync、shell 和 cron(或 systemd),就能构建稳定可靠的灾备流程。
一、基础备份脚本:带日志和排除项
先写一个可复用的 shell 脚本,放在 /usr/local/bin/backup-rsync.sh:
- 使用 -aAXv 保证权限、ACL、扩展属性和详细输出
- 加 --delete 保持目标与源严格一致(慎用,建议先试运行)
- 用 --exclude 过滤临时/虚拟路径,如
/proc、/sys、/dev、/run、/tmp、/backup - 记录时间戳和执行结果到日志,便于排查
示例内容:
#!/bin/bash
SOURCE="/home/oneh/documents/"
DEST="/backup/documents/"
LOG="/var/log/backup-rsync.log"
DATE=$(date "+%Y-%m-%d %H:%M:%S")
<p>echo "[$DATE] 开始备份: $SOURCE → $DEST" >> "$LOG"
rsync -aAXv --delete \
--exclude={"/proc/<em>","/sys/</em>","/dev/<em>","/run/</em>","/tmp/*","/backup"} \
"$SOURCE" "$DEST" >> "$LOG" 2>&1
if [ $? -eq 0 ]; then
echo "[$DATE] 备份成功" >> "$LOG"
else
echo "[$DATE] 备份失败" >> "$LOG"
fi
保存后赋予执行权限:chmod +x /usr/local/bin/backup-rsync.sh
二、实现真正增量:硬链接快照(节省空间)
单纯覆盖备份会浪费磁盘。用 --link-dest 实现“每日快照 + 硬链接去重”,同一文件只存一份,其余日期目录通过硬链接引用。
- 每天生成带时间戳的独立备份目录,如
/backup/20260729_0200 - 让新备份复用上一次完整目录中的未变文件(用硬链接)
- 维护一个
/backup/latest符号链接指向最新备份
关键命令片段:
CURRENT="/backup/$(date +%Y%m%d_%H%M)"
LATEST="/backup/latest"
mkdir -p "$CURRENT"
rsync -aAXv --delete \
--link-dest="$LATEST" \
--exclude={"/proc/*","/sys/*","/dev/*","/run/*","/tmp/*","/backup"} \
"$SOURCE" "$CURRENT"
rm -f "$LATEST"
ln -s "$CURRENT" "$LATEST"
三、自动触发:cron 定时 or systemd 关机前执行
两种主流方式,按场景选:
-
cron 定时(推荐日常周期备份):编辑 root 的 crontab:
sudo crontab -e,添加一行0 2 * * * /usr/local/bin/backup-rsync.sh(每天凌晨 2 点执行) -
systemd 关机前执行(防意外断电/关机丢数据):创建服务文件
/etc/systemd/system/pre-shutdown-backup.service,设置Before=shutdown.target,并启用它
四、异地灾备:走 SSH + 密钥免密登录
把本地数据同步到远程服务器,只需改目标地址格式,并确保已配置 SSH 免密:
- 在本地生成密钥:
ssh-keygen -t ed25519 - 推送公钥到远端:
ssh-copy-id user@192.168.10.100 - 脚本中目标写成:
user@192.168.10.100:/backup/remote-docs/ - 加上
-e "ssh -p 2222"可指定非标端口
完整异地命令示例:rsync -aAXvz --delete -e "ssh -p 2222" /home/oneh/documents/ user@192.168.10.100:/backup/
不复杂但容易忽略:路径末尾斜杠决定同步行为(/source/ 同步内容,/source 同步目录本身),每次上线前用 -n(dry-run)试跑一次更稳妥。


















