本文最后更新于 2025-10-24,文章内容可能已经过时。

架构

备份策略

热备份

PVE内系统

win虚拟机的备份,主要是卸载主存储盘H:/后,对系统盘以及docker盘进行完整打包备份,必要时可实现将备份直接还原成系统镜像,每3个月备份一次,备份目标盘为主存储盘H:/PVE/WIN(待完成)

Debian虚拟机主要是Halo建站服务专用,每1个月将docker容器备份成镜像及数据库备份,备份目标盘为主存储盘H:/PVE/Debian/Docker(待完成)

OpenWRT系统备份

对系统各插件配置进行备份,及对系统进行镜像备份,每三个月一次,备份目标盘为主存储盘H:/OPenWRT(待完成)

照片备份

win虚拟机搭建immich,进行手机照片备份服务,端口映射到域名上即可,每天备份(已完成)

文件备份

办公电脑通过Syncthing服务时刻增量自动备份到win虚拟机中的H:/ (已完成)

冷备份

每周将win虚拟机中H:/自动挂载到openwrt中,然后镜像备份到同规格硬盘中(已完成)
自动脚本如下:

#!/bin/sh

# 镜像备份脚本 - 专为网络共享到本地硬盘的完整镜像设计
#已经将网络共享的挂载信息配置在了/etc/config/fstab文件中,这样可以直接使用mount命令挂载。

LOG_FILE="/var/log/mirror_backup.log"
LOCK_FILE="/var/run/mirror_backup.lock"

# 信号处理
cleanup() {
    log "收到中断信号,开始清理..."
    sync
    umount /mnt/win_share 2>/dev/null
    umount /mnt/backup_disk 2>/dev/null
    rm -f "$LOCK_FILE"
    log "清理完成,脚本退出"
    exit 1
}

trap cleanup INT TERM

log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
    [ -t 0 ] && echo "$1"
}

# 检查锁文件
check_lock() {
    if [ -f "$LOCK_FILE" ]; then
        log "❌ 错误:备份脚本已在运行中"
        exit 1
    fi
    echo $$ > "$LOCK_FILE"
}

# 挂载检查函数
safe_mount() {
    local mount_point=$1
    local mount_cmd=$2
    local mount_name=$3
    
    if grep -qs "$mount_point" /proc/mounts; then
        log "⚠️ $mount_name 已经挂载"
        return 0
    fi
    
    mkdir -p "$mount_point"
    log "挂载 $mount_name..."
    
    if eval "$mount_cmd"; then
        log "✅ $mount_name 挂载成功"
        return 0
    else
        log "❌ $mount_name 挂载失败"
        return 1
    fi
}

log "=== 开始镜像备份任务 ==="
check_lock

# 变量设置
BACKUP_SOURCE="/mnt/win_share"
BACKUP_TARGET="/mnt/backup_disk"

# 清理残留挂载
if ! grep -qs "$BACKUP_SOURCE" /proc/mounts; then
    umount "$BACKUP_SOURCE" 2>/dev/null
fi
if ! grep -qs "$BACKUP_TARGET" /proc/mounts; then
    umount "$BACKUP_TARGET" 2>/dev/null
fi
sleep 2

# 挂载网络共享
if ! safe_mount "$BACKUP_SOURCE" "mount /mnt/win_share" "网络共享"; then
    rm -f "$LOCK_FILE"
    exit 1
fi

# 挂载备份硬盘
if ! safe_mount "$BACKUP_TARGET" "mount -t ntfs-3g -o rw,noatime /dev/sda1 /mnt/backup_disk" "备份硬盘"; then
    umount "$BACKUP_SOURCE"
    rm -f "$LOCK_FILE"
    exit 1
fi

# 验证目录
if [ ! -d "$BACKUP_SOURCE" ] || [ ! -r "$BACKUP_SOURCE" ]; then
    log "❌ 错误:源目录不可访问"
    umount "$BACKUP_SOURCE"
    umount "$BACKUP_TARGET"
    rm -f "$LOCK_FILE"
    exit 1
fi

# 记录开始状态
log "备份源: $BACKUP_SOURCE"
log "备份目标: $BACKUP_TARGET"
SOURCE_SIZE=$(du -sh "$BACKUP_SOURCE/" 2>/dev/null | cut -f1 || echo "未知")
TARGET_START_SIZE=$(du -sh "$BACKUP_TARGET/" 2>/dev/null | cut -f1 || echo "未知")
log "源目录大小: $SOURCE_SIZE"
log "目标目录开始大小: $TARGET_START_SIZE"

# 执行镜像备份
log "开始镜像同步..."
start_time=$(date +%s)

rsync -ahiv --delete --delete-excluded \
    --progress \
    --stats \
    --modify-window=2 \
    --no-implied-dirs \
    --protect-args \
    --exclude='*.tmp' \
    --exclude='*.temp' \
    --exclude='Thumbs.db' \
    --exclude='.DS_Store' \
    --exclude='._*' \
    --exclude='.Trash-*/' \
    --exclude='@eaDir/' \
    --exclude='System Volume Information/' \
    "$BACKUP_SOURCE/" "$BACKUP_TARGET/" >> "$LOG_FILE" 2>&1

RSYNC_RESULT=$?
end_time=$(date +%s)
duration=$((end_time - start_time))

log "镜像同步完成,耗时: ${duration}秒"

# 分析同步结果
case $RSYNC_RESULT in
    0)
        log "✅ 镜像备份成功完成"
        ;;
    23|24)
        log "⚠️ 备份完成,但有部分文件问题 (代码: $RSYNC_RESULT)"
        ;;
    *)
        log "❌ 备份失败 (代码: $RSYNC_RESULT)"
        ;;
esac

# 记录统计信息
if grep -q "Number of files:" "$LOG_FILE"; then
    log "同步统计:"
    tail -n 10 "$LOG_FILE" | grep -E "(Number of files|Number of files transferred|Total file size|Total transferred file size)" >> "$LOG_FILE"
fi

# 记录结束状态
TARGET_END_SIZE=$(du -sh "$BACKUP_TARGET/" 2>/dev/null | cut -f1 || echo "未知")
log "目标目录结束大小: $TARGET_END_SIZE"

# 验证备份一致性(可选)
log "验证备份一致性..."
SOURCE_COUNT=$(find "$BACKUP_SOURCE" -type f 2>/dev/null | wc -l)
TARGET_COUNT=$(find "$BACKUP_TARGET" -type f 2>/dev/null | wc -l)

log "源文件数量: $SOURCE_COUNT"
log "目标文件数量: $TARGET_COUNT"

if [ "$SOURCE_COUNT" -gt 0 ] && [ "$TARGET_COUNT" -gt 0 ]; then
    CONSISTENCY=$((TARGET_COUNT * 100 / SOURCE_COUNT))
    log "备份一致性: $CONSISTENCY%"
    
    if [ "$CONSISTENCY" -lt 95 ]; then
        log "⚠️ 警告:备份一致性较低"
    fi
fi

# 完成清理
log "卸载挂载点..."
sync
umount "$BACKUP_SOURCE" 2>/dev/null
umount "$BACKUP_TARGET" 2>/dev/null
rm -f "$LOCK_FILE"

log "✅ 镜像备份任务完成"
log "=========================================="