跳转到内容

备份策略

数据是服务器上最有价值的资产。硬件可以更换,软件可以重装,但丢失的数据往往无法恢复。本文介绍从基础到进阶的备份方案,帮助你构建可靠的数据保护体系。

在制定策略之前,先理解三种基本备份类型:

类型说明优点缺点
完全备份每次备份所有数据恢复简单快速耗时长、占用空间大
增量备份仅备份自上次备份后变化的数据速度快、节省空间恢复时需要完整链路
差异备份备份自上次完全备份后变化的数据恢复较简单随时间推移数据量增长

推荐的备份策略(祖父-父-子方案):

  • 每日:增量备份
  • 每周:完全备份
  • 每月:完全备份离线归档

rsync 是最常用的文件同步工具,支持增量传输,只复制变化的部分。

Terminal window
# 本地目录同步
rsync -avh --progress /var/www/ /backup/www/
# 参数说明:
# -a 归档模式(保留权限、时间戳、符号链接等)
# -v 详细输出
# -h 人类可读的文件大小
# --progress 显示传输进度
Terminal window
# 推送到远程服务器
rsync -avhz --progress /var/www/ user@backup-server:/backup/www/
# 从远程服务器拉取
rsync -avhz --progress user@backup-server:/data/ /local/backup/data/
# -z 启用压缩传输,适合网络带宽有限的场景
Terminal window
# 排除不需要备份的目录/文件
rsync -avh \
--exclude='*.log' \
--exclude='cache/' \
--exclude='tmp/' \
--delete \
/var/www/ /backup/www/
# --delete 删除目标端多余的文件,保持完全一致
# 注意:--delete 有风险,首次使用建议先加 --dry-run 预演
rsync -avhn --delete /var/www/ /backup/www/ # -n 等同于 --dry-run

rsync 增量备份脚本(带硬链接)

Section titled “rsync 增量备份脚本(带硬链接)”

利用硬链接实现高效的增量备份,每次备份看起来都是完整的,但只占用变化文件的空间:

/usr/local/bin/rsync_backup.sh
#!/bin/bash
# 使用硬链接的增量备份
SOURCE="/var/www"
BACKUP_BASE="/backup/www"
DATE=$(date +%Y-%m-%d_%H%M%S)
LATEST="${BACKUP_BASE}/latest"
TARGET="${BACKUP_BASE}/${DATE}"
# 如果存在上次备份,使用硬链接
if [ -d "$LATEST" ]; then
LINK_DEST="--link-dest=${LATEST}"
else
LINK_DEST=""
fi
# 执行备份
rsync -avh --delete $LINK_DEST "${SOURCE}/" "${TARGET}/"
# 更新 latest 链接
rm -f "$LATEST"
ln -s "$TARGET" "$LATEST"
# 删除 30 天前的备份
find "$BACKUP_BASE" -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +
echo "[$(date)] 备份完成: ${TARGET}"

tar 适合对特定目录做完整打包归档。

Terminal window
# 创建压缩归档
tar czf /backup/www-$(date +%Y%m%d).tar.gz -C / var/www
# 使用 xz 压缩(压缩率更高,但速度较慢)
tar cJf /backup/www-$(date +%Y%m%d).tar.xz -C / var/www
# 备份时排除特定内容
tar czf /backup/www-$(date +%Y%m%d).tar.gz \
--exclude='*.log' \
--exclude='cache' \
-C / var/www

tar 支持基于快照文件的增量备份:

Terminal window
# 第一次运行 —— 完全备份(创建快照文件)
tar czf /backup/www-full-$(date +%Y%m%d).tar.gz \
--listed-incremental=/backup/www.snar \
-C / var/www
# 后续运行 —— 增量备份(基于快照文件)
tar czf /backup/www-incr-$(date +%Y%m%d_%H%M%S).tar.gz \
--listed-incremental=/backup/www.snar \
-C / var/www

恢复增量备份时,需要按顺序先恢复完全备份,再依次恢复每个增量:

Terminal window
# 恢复完全备份
tar xzf /backup/www-full-20260301.tar.gz -C /
# 按顺序恢复增量备份
tar xzf /backup/www-incr-20260302_020000.tar.gz -C /
tar xzf /backup/www-incr-20260303_020000.tar.gz -C /

BorgBackup(简称 Borg)是一款现代化的去重压缩备份工具,非常适合服务器备份场景。

Terminal window
sudo dnf install epel-release -y
sudo dnf install borgbackup -y
Terminal window
# 本地仓库
borg init --encryption=repokey /backup/borg-repo
# 远程仓库(通过 SSH)
borg init --encryption=repokey ssh://user@backup-server/backup/borg-repo
# 加密密钥会提示你输入密码,请务必妥善保管!
Terminal window
# 创建备份存档
borg create \
--verbose \
--stats \
--progress \
--compression zstd,3 \
/backup/borg-repo::'{hostname}-{now:%Y-%m-%d_%H%M%S}' \
/var/www \
/etc \
/home \
--exclude '/home/*/.cache' \
--exclude '*.tmp'
Terminal window
# 列出所有存档
borg list /backup/borg-repo
# 查看某个存档的内容
borg list /backup/borg-repo::myserver-2026-03-20_020000
# 恢复到指定目录
cd /tmp/restore
borg extract /backup/borg-repo::myserver-2026-03-20_020000
# 仅恢复特定路径
borg extract /backup/borg-repo::myserver-2026-03-20_020000 var/www
Terminal window
# 保留策略:7 个每日、4 个每周、6 个每月
borg prune \
--verbose \
--list \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=6 \
/backup/borg-repo
# 释放已删除存档的磁盘空间
borg compact /backup/borg-repo
/usr/local/bin/borg_backup.sh
#!/bin/bash
# BorgBackup 自动化备份脚本
set -euo pipefail
# 配置
export BORG_REPO="/backup/borg-repo"
export BORG_PASSPHRASE="your_secure_passphrase" # 生产环境建议使用密钥文件
BACKUP_NAME="{hostname}-{now:%Y-%m-%d_%H%M%S}"
LOG_FILE="/var/log/borg_backup.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "开始备份..."
# 创建备份
borg create \
--verbose \
--stats \
--compression zstd,3 \
--exclude '/home/*/.cache' \
--exclude '/var/tmp/*' \
--exclude '/var/log/*.gz' \
"${BORG_REPO}::${BACKUP_NAME}" \
/etc \
/home \
/var/www \
/var/lib/mysql \
2>&1 | tee -a "$LOG_FILE"
log "备份完成,开始清理旧存档..."
# 清理旧备份
borg prune \
--verbose \
--list \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=6 \
"$BORG_REPO" \
2>&1 | tee -a "$LOG_FILE"
borg compact "$BORG_REPO" 2>&1 | tee -a "$LOG_FILE"
log "所有操作完成。"
# 取消密码变量
unset BORG_PASSPHRASE
Terminal window
chmod 700 /usr/local/bin/borg_backup.sh
Terminal window
sudo crontab -e
# 每天凌晨 2 点执行 Borg 备份
0 2 * * * /usr/local/bin/borg_backup.sh >> /var/log/borg_backup.log 2>&1
# 每天凌晨 3 点执行 rsync 备份
0 3 * * * /usr/local/bin/rsync_backup.sh >> /var/log/rsync_backup.log 2>&1

systemd timer 比 cron 更灵活,支持日志集成和依赖管理。

Terminal window
# 创建 service 单元
sudo tee /etc/systemd/system/borg-backup.service > /dev/null <<'EOF'
[Unit]
Description=BorgBackup 每日备份
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/borg_backup.sh
Nice=19
IOSchedulingClass=idle
EOF
# 创建 timer 单元
sudo tee /etc/systemd/system/borg-backup.timer > /dev/null <<'EOF'
[Unit]
Description=每日凌晨 2 点运行 BorgBackup
[Timer]
OnCalendar=*-*-* 02:00:00
RandomizedDelaySec=600
Persistent=true
[Install]
WantedBy=timers.target
EOF
# 启用定时器
sudo systemctl daemon-reload
sudo systemctl enable --now borg-backup.timer
# 查看定时器状态
systemctl list-timers borg-backup.timer
# 手动触发一次测试
sudo systemctl start borg-backup.service
journalctl -u borg-backup.service -f

本地备份无法防范机房级别的故障(火灾、断电、硬件批量损坏)。至少应有一份异地备份。

/usr/local/bin/offsite_backup.sh
#!/bin/bash
# 将本地备份同步到远程服务器
REMOTE_USER="backup"
REMOTE_HOST="offsite-backup.example.com"
REMOTE_PATH="/backup/$(hostname)"
LOCAL_BACKUP="/backup/borg-repo"
# 使用 SSH 密钥认证(避免密码交互)
rsync -avhz --progress \
-e "ssh -i /root/.ssh/backup_key -o StrictHostKeyChecking=yes" \
"${LOCAL_BACKUP}/" \
"${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/"
Terminal window
# 安装 rclone
sudo dnf install rclone -y
# 配置(交互式)
rclone config
# 按提示配置 S3 兼容存储(如 AWS S3、MinIO、阿里云 OSS 等)
# 同步备份到对象存储
rclone sync /backup/borg-repo remote:my-backup-bucket/borg-repo \
--transfers=4 \
--progress
Terminal window
# 创建临时恢复目录
mkdir -p /tmp/restore-test
cd /tmp/restore-test
# 从最新存档恢复
export BORG_REPO="/backup/borg-repo"
export BORG_PASSPHRASE="your_secure_passphrase"
LATEST=$(borg list --last 1 --short "$BORG_REPO")
echo "恢复存档: ${LATEST}"
borg extract "${BORG_REPO}::${LATEST}"
# 验证文件完整性
echo "文件数量: $(find . -type f | wc -l)"
echo "总大小: $(du -sh .)"
# 对比关键文件
diff /etc/nginx/nginx.conf /tmp/restore-test/etc/nginx/nginx.conf
diff -r /var/www/html/ /tmp/restore-test/var/www/html/ | head -20
# 清理
rm -rf /tmp/restore-test
unset BORG_PASSPHRASE
/usr/local/bin/test_restore.sh
#!/bin/bash
# 自动化备份恢复测试
set -euo pipefail
RESTORE_DIR="/tmp/restore-test-$(date +%s)"
BORG_REPO="/backup/borg-repo"
export BORG_PASSPHRASE="your_secure_passphrase"
MAILTO="admin@example.com"
RESULT="成功"
mkdir -p "$RESTORE_DIR"
cd "$RESTORE_DIR"
# 获取最新存档
LATEST=$(borg list --last 1 --short "$BORG_REPO")
# 尝试恢复
if borg extract "${BORG_REPO}::${LATEST}"; then
FILE_COUNT=$(find . -type f | wc -l)
TOTAL_SIZE=$(du -sh . | awk '{print $1}')
# 基本验证
if [ "$FILE_COUNT" -eq 0 ]; then
RESULT="失败 - 恢复文件数为 0"
fi
else
RESULT="失败 - borg extract 返回错误"
fi
# 发送报告
REPORT="备份恢复测试报告\n\n"
REPORT+="日期: $(date)\n"
REPORT+="存档: ${LATEST}\n"
REPORT+="结果: ${RESULT}\n"
REPORT+="文件数: ${FILE_COUNT:-N/A}\n"
REPORT+="数据量: ${TOTAL_SIZE:-N/A}\n"
echo -e "$REPORT" | mail -s "[备份测试] 恢复测试${RESULT}" "$MAILTO"
# 清理
rm -rf "$RESTORE_DIR"
unset BORG_PASSPHRASE

将恢复测试加入定时任务,建议每月执行一次:

Terminal window
# 每月 1 号凌晨 5 点运行恢复测试
0 5 1 * * /usr/local/bin/test_restore.sh >> /var/log/restore_test.log 2>&1

文件备份之外,数据库需要专门的备份策略。

Terminal window
# 完整备份
mysqldump --all-databases --single-transaction --quick \
--routines --triggers \
-u root -p | gzip > /backup/mysql-$(date +%Y%m%d).sql.gz
# 指定数据库
mysqldump --single-transaction -u root -p mydb | gzip > /backup/mydb-$(date +%Y%m%d).sql.gz
# 恢复
gunzip < /backup/mysql-20260320.sql.gz | mysql -u root -p
Terminal window
# 完整备份
sudo -u postgres pg_dumpall | gzip > /backup/postgres-$(date +%Y%m%d).sql.gz
# 指定数据库
sudo -u postgres pg_dump mydb | gzip > /backup/mydb-$(date +%Y%m%d).sql.gz
# 恢复
gunzip < /backup/postgres-20260320.sql.gz | sudo -u postgres psql

制定备份方案时,确认以下每一项:

  • 明确需要备份的数据范围(配置文件、网站数据、数据库、用户数据)
  • 选择合适的备份工具和类型
  • 设定备份频率(每日/每周/每月)
  • 配置自动化调度
  • 设置备份保留策略(保留多少份、保留多长时间)
  • 至少有一份异地备份
  • 备份数据加密(尤其是异地/云端备份)
  • 每月至少进行一次恢复测试
  • 监控备份任务是否按时成功执行
  • 记录完整的恢复步骤文档