日常备份脚本怎样设计才最安全可靠

wen 实用脚本 2

本文目录导读:

日常备份脚本怎样设计才最安全可靠

  1. 核心原则(安全+可靠)
  2. 推荐的技术栈
  3. 完整脚本设计(基于 restic,最安全可靠)
  4. 如果必须使用 rsync(带加密的同步方案)
  5. 最佳实践总结

设计一个既安全可靠的日常备份脚本,核心在于:加密传输与存储、自动验证完整性、3-2-1备份策略、以及防御性编程

安全是指数据不会被泄露或篡改(防止勒索软件同步备份、防止中间人攻击),可靠是指备份真正可用,而不是一堆损坏的文件。

以下是设计这样一个脚本的详细指南,包含核心原则、关键代码片段和完整模板。


核心原则(安全+可靠)

  1. 3-2-1 备份策略:至少 3 份副本(1份源+2份备份),存储在 2 种不同介质上(如本地硬盘+云存储),1 份在异地(不同城市/机房)。
  2. 加密(重中之重):备份数据必须端到端加密,且密钥与备份数据分开存放,推荐使用 GPGage
  3. 验证机制:备份完成后,必须自动验证(如校验 SHA256 哈希、测试解压或挂载)。
  4. 传输安全:远程传输使用 SSH over SFTPRsync over SSHHTTPS,绝对避免明文 FTP。
  5. 幂等性与增量备份:设计脚本使其可以反复运行而不产生重复数据,使用 rsyncrestic 的增量特性。
  6. 防御性编程:脚本中必须有错误处理、日志记录、锁文件(防止并发)、以及失败告警

推荐的技术栈

功能 推荐工具 理由
加密存储 restic 自带加密、去重、增量、云备份、验证功能,是目前最安全可靠的方案之一。
文件同步 rsync 增量、校验、可通过 SSH 加密传输,适合本地或纯文件同步。
加密文件 age / gpg 轻量级加密,age 更现代更易用。
完整性校验 sha256sum 标准工具,生成哈希文件。
通知告警 curl + Telegram/Slack/邮件 实时反馈异常。
调度器 systemd timer 比 crontab 更可控,支持依赖、日志、资源限制。

建议:如果你的主要诉求是“安全+可靠”,强烈推荐直接使用 restic,它几乎解决了所有痛点,如果必须手动写 rsync,请参考后面的脚本模板。


完整脚本设计(基于 restic,最安全可靠)

以下脚本满足:增量备份、端到端加密、自动清理、完整性检查、错误告警

环境准备

# 安装 restic
wget -qO- https://github.com/restic/restic/releases/latest/download/restic_linux_amd64.bz2 | bzcat > /usr/local/bin/restic
chmod +x /usr/local/bin/restic
# 初始化仓库(执行一次)
export RESTIC_REPOSITORY="/mnt/backup/my-backup"  # 本地或远程路径
export RESTIC_PASSWORD="your-very-strong-password-here"  # 加密密码,绝对不能写死!使用密钥文件
restic init

备份脚本 (/usr/local/bin/safe-backup.sh)

#!/bin/bash
set -euo pipefail  # 严格模式:遇到错误立即退出,变量未定义时报错
# ---------- 配置区域(安全处理) ----------
# 使用密钥文件而不是环境变量,避免进程列表泄露密码
RESTIC_REPOSITORY="/mnt/backup/my-backup"
RESTIC_PASSWORD_FILE="/etc/restic/password.txt"  # 权限为 600,只给 root 读
BACKUP_SOURCE="/var/www/html /home /etc"
EXCLUDE_FILE="/etc/restic/exclude.txt"  # *.log, cache/
BACKUP_TAG="daily-auto"
LOG_FILE="/var/log/backup-daily.log"
LOCK_FILE="/tmp/backup-daily.lock"
# 通知配置(使用独立 API 密钥)
TELEGRAM_BOT_TOKEN="your-token"
TELEGRAM_CHAT_ID="your-chat-id"
# ---------- 防御性编程:单例模式 ----------
if [ -f "$LOCK_FILE" ]; then
    echo "$(date): 另一个备份进程正在运行,跳过本次执行。" >> "$LOG_FILE"
    exit 1
fi
trap 'rm -f "$LOCK_FILE"; exit' EXIT INT TERM
touch "$LOCK_FILE"
# ---------- 日志函数 ----------
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
send_alert() {
    curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
        -d "chat_id=${TELEGRAM_CHAT_ID}" \
        -d "text=⚠️ 备份失败: $1" > /dev/null
}
# ---------- 核心备份逻辑 ----------
log "开始备份: ${BACKUP_SOURCE}"
if restic backup \
    --repo "$RESTIC_REPOSITORY" \
    --password-file "$RESTIC_PASSWORD_FILE" \
    --one-file-system \
    --tag "$BACKUP_TAG" \
    --exclude-file "$EXCLUDE_FILE" \
    --verbose \
    $BACKUP_SOURCE 2>&1 | tee -a "$LOG_FILE"; then
    log "备份上传完成,开始验证..." 
    # 可靠性:检查最新快照是否可读
    if restic check \
        --repo "$RESTIC_REPOSITORY" \
        --password-file "$RESTIC_PASSWORD_FILE" \
        --read-data-subset=1% 2>&1 | tee -a "$LOG_FILE"; then
        log "✅ 完整性验证通过"
    else
        log "❌ 完整性验证失败,数据可能损坏!"
        send_alert "完整性验证失败,请立即检查仓库: ${RESTIC_REPOSITORY}"
        exit 2
    fi
    # 清理策略:保留最近7天每天,最近4周每周,最近6个月每月,其余删除
    log "执行清理策略..."
    restic forget \
        --repo "$RESTIC_REPOSITORY" \
        --password-file "$RESTIC_PASSWORD_FILE" \
        --keep-daily 7 \
        --keep-weekly 4 \
        --keep-monthly 6 \
        --prune 2>&1 | tee -a "$LOG_FILE"
    log "✅ 备份成功完成"
else
    log "❌ 备份执行失败"
    send_alert "备份执行失败,日志在: ${LOG_FILE}"
    exit 3  # 退出码 3 表示备份错误
fi
exit 0

如何运行

# 设置密钥文件(绝对安全)
echo "your-very-strong-password-here" > /etc/restic/password.txt
chmod 600 /etc/restic/password.txt
chown root:root /etc/restic/password.txt
# 授予执行权限
chmod +x /usr/local/bin/safe-backup.sh
# 测试运行(手动)
bash /usr/local/bin/safe-backup.sh

设置为定时任务 (推荐 systemd timer)

创建服务文件 /etc/systemd/system/backup-daily.service:

[Unit]
Description=Daily Safe Backup
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/safe-backup.sh
# 安全限制:禁止网络访问?根据需要调整
PrivateTmp=true
ProtectSystem=full
ReadWritePaths=/var/log

创建定时器文件 /etc/systemd/system/backup-daily.timer:

[Unit]
Description=Daily Backup Timer
Requires=backup-daily.service
[Timer]
OnCalendar=daily
RandomizedDelaySec=1h  # 随机延迟,避免所有任务同时启动
Persistent=true
[Install]
WantedBy=timers.target

激活定时器:

systemctl daemon-reload
systemctl enable --now backup-daily.timer

如果必须使用 rsync(带加密的同步方案)

rsync 本身不加密,需要配合 SSH 或 GPG 使用,以下是一个安全+可靠的示例:

#!/bin/bash
set -euo pipefail
REMOTE_HOST="backup-server.example.com"
REMOTE_USER="backupuser"
LOCAL_SOURCE="/home/user/Documents"
REMOTE_DEST="/backup/incremental/"
SSH_PORT=2222  # 非默认端口
SNAPSHOT_DIR="/snapshots/backup_$(date +%Y%m%d_%H%M%S)"
LATEST_LINK="/snapshots/latest_backup"
# 1. 创建日期后缀的增量备份目录(硬链接方案,节省空间)
mkdir -p "$SNAPSHOT_DIR"
# 2. 使用 rsync 通过 SSH,启用压缩、校验、硬链接
rsync -avz \
    --link-dest="$LATEST_LINK" \  # 与上次备份建立硬链接,节省空间但保持完整目录
    --delete \                    # 删除源中不再存在的文件
    --chmod=Du=rwx,Dgo=rx,Fu=rw,Fgo=r \
    --log-file="/var/log/rsync_backup.log" \
    -e "ssh -p ${SSH_PORT} -i /root/.ssh/backup_key" \
    "$LOCAL_SOURCE" \
    "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DEST}${SNAPSHOT_DIR}/"
# 3. 更新最新链接
ssh -p "$SSH_PORT" -i /root/.ssh/backup_key "${REMOTE_USER}@${REMOTE_HOST}" \
    "rm -f ${REMOTE_DEST}${LATEST_LINK}; ln -s ${SNAPSHOT_DIR} ${REMOTE_DEST}${LATEST_LINK}"
# 4. 验证:使用校验和的子集
echo "Verifying checksums..."
cd "$LOCAL_SOURCE"
find . -type f -name "*.txt" -exec sha256sum {} \; > /tmp/checksums_local.txt
ssh -p "$SSH_PORT" -i /root/.ssh/backup_key "${REMOTE_USER}@${REMOTE_HOST}" \
    "cd ${REMOTE_DEST}${SNAPSHOT_DIR} && sha256sum -c /tmp/checksums_local.txt"
echo "✅ Checksum verification passed."
# 5. 清理:保留最近30天的快照
ssh -p "$SSH_PORT" -i /root/.ssh/backup_key "${REMOTE_USER}@${REMOTE_HOST}" \
    "find ${REMOTE_DEST} -maxdepth 1 -type d -name 'backup_*' -mtime +30 -exec rm -rf {} \;"

注意:这种做法的安全性取决于 SSH 密钥的权限管理,如果远程服务器被入侵,所有数据都会暴露,因此强烈推荐使用 restic


最佳实践总结

安全性措施 实现方式
加密 使用 resticage/gpg 加密,密钥文件权限 600
传输加密 SSH (SFTP)、Rsync over SSH、HTTPS
防止篡改 定期对备份仓库执行 restic checksha256sum
防勒索软件 备份目标不能自动挂载且可写(使用 WORM 媒体或云对象存储不可变版本)
防误删 配置 restic forget --keep-daily 7 自动清理,留有余地
记录审计 日志文件定期轮转,记录每次操作的退出码和时间
告警 失败后通过 Telegram/邮件/Webhook 通知,退出码用于监控系统(如 Prometheus)

也是最重要的:定期进行恢复演练。 每季度至少一次从备份中恢复到一个临时环境并验证数据完整性,没有经过验证的备份,等于没有备份。

上一篇实用脚本有哪些提高工作效率的写法

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!