#!/usr/bin/env bash # 从 backup.sh 的产物恢复。用法:scripts/restore.sh <备份目录> # 会停服 → 恢复 PG(逻辑)+ 各数据卷(覆盖)→ 重启。务必先确认目录正确,操作不可逆。 set -euo pipefail COMPOSE="docker compose -f docker-compose.prod.yml" DIR="${1:?用法: scripts/restore.sh <备份目录>}" [ -d "$DIR" ] || { echo "目录不存在: $DIR"; exit 1; } echo "[restore] 从 $DIR 恢复,将覆盖现有数据。Ctrl-C 取消,5s 后继续…"; sleep 5 echo "[restore] 停应用(保留基建跑着以便恢复 PG)…" $COMPOSE stop gateway dispatcher mcp-go mcp-py admin || true # PostgreSQL:逻辑恢复(先清库再灌)。 if [ -f "$DIR/postgres.sql.gz" ]; then echo "[restore] postgres…" $COMPOSE up -d postgres; sleep 5 $COMPOSE exec -T postgres psql -U sundynix -d sundynix -c \ "DROP SCHEMA public CASCADE; CREATE SCHEMA public;" gunzip -c "$DIR/postgres.sql.gz" | $COMPOSE exec -T postgres psql -U sundynix -d sundynix fi # 数据卷恢复(停服 → 清空卷 → 解 tar)。 restore_volume () { # $1=卷后缀 $2=tar 文件 [ -f "$DIR/$2" ] || { echo "[restore] 无 $2,跳过"; return; } local full; full="$(docker volume ls --format '{{.Name}}' | grep -E "_${1}\$" | head -1)" [ -z "$full" ] && { echo "[restore] 卷 $1 未找到,跳过"; return; } echo "[restore] volume $full ← $2" docker run --rm -v "$full":/data -v "$(cd "$DIR" && pwd)":/in alpine \ sh -c "rm -rf /data/* && cd /data && tar xzf /in/$2" } echo "[restore] 停基建以恢复卷…"; $COMPOSE down restore_volume milvus_data milvus_data.tar.gz restore_volume minio_data minio_data.tar.gz restore_volume neo4j_data neo4j_data.tar.gz restore_volume nats_data nats_data.tar.gz echo "[restore] 重启全部…"; $COMPOSE -f docker-compose.prod.yml up -d echo "[restore] 完成。若恢复到新机,记得把备份里的 env.bak 还原为 .env。"