加固备份恢复本地基线(07-26-internal-ops-recovery-baseline)
这个提交包含在:
+73
-10
@@ -1,8 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
BACKUP_FILE="${1:-${BACKUP_FILE:-}}"
|
||||
if [[ -z "${BACKUP_FILE:-}" ]]; then
|
||||
echo "Usage: $0 <backup-file.dump>" >&2
|
||||
@@ -19,16 +17,69 @@ if [[ -z "${DATABASE_URL:-}" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[INFO] DB restore start: $BACKUP_FILE"
|
||||
RESTORE_SCOPE="${RESTORE_SCOPE:-}"
|
||||
RESTORE_CONFIRM_DATABASE="${RESTORE_CONFIRM_DATABASE:-}"
|
||||
DB_TOOL_MODE="${DB_TOOL_MODE:-auto}"
|
||||
|
||||
if command -v pg_restore >/dev/null 2>&1; then
|
||||
if [[ "$DB_TOOL_MODE" != "auto" && "$DB_TOOL_MODE" != "host" && "$DB_TOOL_MODE" != "docker" ]]; then
|
||||
echo "[ERR] DB_TOOL_MODE must be auto, host, or docker" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$RESTORE_SCOPE" != "shadow" ]]; then
|
||||
echo "[ERR] RESTORE_SCOPE=shadow is required; production restore is not available from this command path" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$RESTORE_CONFIRM_DATABASE" ]]; then
|
||||
echo "[ERR] RESTORE_CONFIRM_DATABASE is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
validate_dump_with_host() {
|
||||
pg_restore --list "$BACKUP_FILE" >/dev/null
|
||||
}
|
||||
|
||||
validate_shadow_database_name() {
|
||||
local database_name="$1"
|
||||
if [[ ! "$database_name" =~ (^|[_-])(shadow|drill|restore_test)([_-]|$) ]]; then
|
||||
echo "[ERR] restore target name is not an explicit shadow/drill database" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
restore_with_host() {
|
||||
local actual_database
|
||||
actual_database="$(psql "$DATABASE_URL" -Atqc 'SELECT current_database()')"
|
||||
if [[ -z "$actual_database" || "$actual_database" != "$RESTORE_CONFIRM_DATABASE" ]]; then
|
||||
echo "[ERR] restore target confirmation mismatch: actual=${actual_database:-unknown}" >&2
|
||||
exit 1
|
||||
fi
|
||||
validate_shadow_database_name "$actual_database"
|
||||
echo "[INFO] DB restore target confirmed: $actual_database (shadow)"
|
||||
pg_restore --clean --if-exists --no-owner --no-acl -d "$DATABASE_URL" "$BACKUP_FILE"
|
||||
echo "[OK] DB restore done (pg_restore): $BACKUP_FILE"
|
||||
exit 0
|
||||
}
|
||||
|
||||
if [[ "$DB_TOOL_MODE" != "docker" ]] && command -v pg_restore >/dev/null 2>&1 && command -v psql >/dev/null 2>&1; then
|
||||
if validate_dump_with_host; then
|
||||
restore_with_host
|
||||
echo "[OK] DB restore done (pg_restore): $BACKUP_FILE"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$DB_TOOL_MODE" == "host" ]]; then
|
||||
echo "[ERR] host pg_restore could not validate the dump" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "[WARN] host pg_restore could not validate the dump; trying docker fallback" >&2
|
||||
fi
|
||||
|
||||
if [[ "$DB_TOOL_MODE" == "host" ]]; then
|
||||
echo "[ERR] DB_TOOL_MODE=host requires pg_restore and psql" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "[ERR] pg_restore not found and docker not available" >&2
|
||||
echo "[ERR] pg_restore/psql not found and docker not available" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -42,8 +93,20 @@ if [[ -z "$POSTGRES_DB" || -z "$POSTGRES_USER" || -z "$POSTGRES_PASSWORD" ]]; th
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "$BACKUP_FILE" | docker exec -i -e PGPASSWORD="$POSTGRES_PASSWORD" "$DB_CONTAINER" \
|
||||
pg_restore --clean --if-exists --no-owner --no-acl -U "$POSTGRES_USER" -d "$POSTGRES_DB"
|
||||
ACTUAL_DATABASE="$(docker exec -e PGPASSWORD="$POSTGRES_PASSWORD" "$DB_CONTAINER" \
|
||||
psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Atqc 'SELECT current_database()')"
|
||||
|
||||
if [[ -z "$ACTUAL_DATABASE" || "$ACTUAL_DATABASE" != "$RESTORE_CONFIRM_DATABASE" ]]; then
|
||||
echo "[ERR] restore target confirmation mismatch: actual=${ACTUAL_DATABASE:-unknown}" >&2
|
||||
exit 1
|
||||
fi
|
||||
validate_shadow_database_name "$ACTUAL_DATABASE"
|
||||
|
||||
docker exec -i "$DB_CONTAINER" pg_restore --list <"$BACKUP_FILE" >/dev/null
|
||||
|
||||
echo "[INFO] DB restore target confirmed: $ACTUAL_DATABASE (shadow)"
|
||||
docker exec -i -e PGPASSWORD="$POSTGRES_PASSWORD" "$DB_CONTAINER" \
|
||||
pg_restore --clean --if-exists --no-owner --no-acl -U "$POSTGRES_USER" -d "$POSTGRES_DB" \
|
||||
<"$BACKUP_FILE"
|
||||
|
||||
echo "[OK] DB restore done (docker exec): $BACKUP_FILE"
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户