nas/服务器记录
本文最后更新于 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 "=========================================="
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Dr.Chen
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果