#!/usr/bin/env bash # backup.sh — 备份 moziplus v2 数据到 NAS set -euo pipefail TARGET_DIR="${MOZIPLUS_V2_DIR:-$HOME/.sanguo_projects/sanguo_moziplus_v2}" NAS_BASE="/Volumes/stock" BACKUP_SUBDIR="moziplus-v2-backups" PM2_NAME="sanguo-moziplus-v2" STOP_SERVICE=false usage() { echo "Usage: $0 [options]" echo "" echo "Options:" echo " --target=DIR 安装目录" echo " --nas=DIR NAS 挂载点 (default: /Volumes/stock)" echo " --stop 备份前停服务(确保数据一致性)" echo " -h, --help 显示帮助" echo "" echo "Note: 如果不停服务,SQLite 可能有不一致的快照" echo " 对于日常备份通常没问题,重要备份建议加 --stop" exit 0 } for arg in "$@"; do case "$arg" in --target=*) TARGET_DIR="${arg#*=}" ;; --nas=*) NAS_BASE="${arg#*=}" ;; --stop) STOP_SERVICE=true ;; -h|--help) usage ;; esac done DATA_DIR="$TARGET_DIR/data" CONFIG_DIR="$TARGET_DIR/config" if [ ! -d "$DATA_DIR" ]; then echo "❌ Data directory not found: $DATA_DIR" && exit 1 fi if [ ! -d "$NAS_BASE" ]; then echo "❌ NAS not mounted: $NAS_BASE" echo " Mount NAS first: open smb://192.168.2.154/" exit 1 fi BACKUP_DIR="$NAS_BASE/$BACKUP_SUBDIR" TIMESTAMP=$(date +%Y%m%d-%H%M%S) BACKUP_NAME="backup-$TIMESTAMP" echo "💾 Backing up moziplus v2" echo " Data: $DATA_DIR" echo " Config: $CONFIG_DIR" echo " Target: $BACKUP_DIR/$BACKUP_NAME" mkdir -p "$BACKUP_DIR" # ── 停服务(可选)── if [ "$STOP_SERVICE" = true ]; then echo "" echo "🛑 Stopping service for consistent backup..." pm2 stop "$PM2_NAME" 2>/dev/null || true fi # ── 备份 ── echo "" echo "📦 Copying data..." mkdir -p "$BACKUP_DIR/$BACKUP_NAME" rsync -a "$DATA_DIR/" "$BACKUP_DIR/$BACKUP_NAME/data/" echo "📦 Copying config..." rsync -a "$CONFIG_DIR/" "$BACKUP_DIR/$BACKUP_NAME/config/" # ── 记录元数据 ── cat > "$BACKUP_DIR/$BACKUP_NAME/metadata.json" << EOF { "timestamp": "$TIMESTAMP", "date": "$(date "+%Y-%m-%dT%H:%M:%S%z")", "source": "$TARGET_DIR", "service_stopped": $STOP_SERVICE, "version": "$(cd "$TARGET_DIR" && python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml","rb"))["project"]["version"])' 2>/dev/null || echo 'unknown')" } EOF # ── 计算大小 ── BACKUP_SIZE=$(du -sh "$BACKUP_DIR/$BACKUP_NAME" | cut -f1) # ── 重启服务 ── if [ "$STOP_SERVICE" = true ]; then echo "" echo "▶️ Restarting service..." pm2 start "$PM2_NAME" 2>/dev/null || true fi # ── 清理旧备份(保留最近 10 个)── echo "" echo "🧹 Cleaning old backups (keeping latest 10)..." cd "$BACKUP_DIR" ls -d backup-* 2>/dev/null | sort | head -n -10 | xargs rm -rf 2>/dev/null || true # ── 完成 ── echo "" echo "✅ Backup completed" echo " Name: $BACKUP_NAME" echo " Size: $BACKUP_SIZE" echo " Path: $BACKUP_DIR/$BACKUP_NAME"