106 lines
2.9 KiB
Bash
Executable File
106 lines
2.9 KiB
Bash
Executable File
#!/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"
|