121 lines
3.8 KiB
Bash
121 lines
3.8 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
|
|
DUMP_FILE=""
|
|
DRY_RUN=0
|
|
FORCE=0
|
|
|
|
if [[ -f "$ENV_FILE" ]]; then
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
source "$ENV_FILE"
|
|
set +a
|
|
fi
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $(basename "$0") --from FILE [--dry-run] [--force]
|
|
|
|
Restores a full database dump (produced by db-export.sh) into the
|
|
ac-database Docker container. The container must be running.
|
|
|
|
Options:
|
|
--from FILE Dump file to restore (.sql or .sql.gz) (required)
|
|
--dry-run Show what would happen without executing
|
|
--force Skip the confirmation prompt
|
|
-h, --help Show this help
|
|
|
|
Examples:
|
|
$(basename "$0") --from backups/2025-01-01_12-00-00.sql.gz
|
|
$(basename "$0") --from /mnt/backup/dump.sql.gz --force
|
|
EOF
|
|
}
|
|
|
|
log() { printf '[db-import] %s\n' "$*"; }
|
|
die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
|
|
|
|
require_ready_db() {
|
|
if ! docker compose ps --status running --services 2>/dev/null | grep -qx 'ac-database'; then
|
|
die "ac-database is not running. Start it with: docker compose up -d ac-database"
|
|
fi
|
|
|
|
log "waiting for MySQL to be ready..."
|
|
local attempts=0
|
|
until docker compose exec -T ac-database bash -lc \
|
|
"mysql -h 127.0.0.1 -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -e 'SELECT 1;'" \
|
|
>/dev/null 2>&1; do
|
|
attempts=$((attempts + 1))
|
|
if [[ $attempts -ge 30 ]]; then
|
|
die "MySQL did not become ready in time. Check: docker logs ac-database"
|
|
fi
|
|
sleep 2
|
|
done
|
|
log "MySQL is ready"
|
|
}
|
|
|
|
mysql_exec() {
|
|
docker compose exec -T ac-database bash -lc \
|
|
"mysql -h 127.0.0.1 -uroot -p\"\$MYSQL_ROOT_PASSWORD\""
|
|
}
|
|
|
|
# ── argument parsing ──────────────────────────────────────────────────────────
|
|
|
|
while (($#)); do
|
|
case "$1" in
|
|
--from) DUMP_FILE="$2"; shift ;;
|
|
--dry-run) DRY_RUN=1 ;;
|
|
--force) FORCE=1 ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) printf 'Unknown option: %s\n\n' "$1" >&2; usage >&2; exit 1 ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# ── validation ────────────────────────────────────────────────────────────────
|
|
|
|
[[ -z "$DUMP_FILE" ]] && { usage >&2; die "--from FILE is required"; }
|
|
[[ -f "$DUMP_FILE" ]] || die "file not found: $DUMP_FILE"
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
# ── preview ───────────────────────────────────────────────────────────────────
|
|
|
|
file_size="$(du -sh "$DUMP_FILE" | cut -f1)"
|
|
|
|
printf '\nMigration plan:\n'
|
|
printf ' Source : %s (%s)\n' "$DUMP_FILE" "$file_size"
|
|
printf ' Target : ac-database container\n\n'
|
|
|
|
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
log "dry-run mode — nothing imported"
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "$FORCE" -eq 0 ]]; then
|
|
printf 'WARNING: this will DROP and recreate all databases in the dump.\n'
|
|
read -r -p "Continue? [y/N] " confirm
|
|
[[ "$confirm" =~ ^[Yy]$ ]] || { log "aborted"; exit 0; }
|
|
fi
|
|
|
|
# ── import ────────────────────────────────────────────────────────────────────
|
|
|
|
require_ready_db
|
|
|
|
log "restoring $DUMP_FILE into ac-database..."
|
|
log "this may take several minutes..."
|
|
|
|
if [[ "$DUMP_FILE" == *.gz ]]; then
|
|
zcat "$DUMP_FILE" | mysql_exec
|
|
else
|
|
mysql_exec < "$DUMP_FILE"
|
|
fi
|
|
|
|
log "import complete"
|
|
log ""
|
|
log "next steps:"
|
|
log " 1. Update realmlist: bash sync-realmlist.sh"
|
|
log " 2. Start the server: bash scripts/prod-deploy.sh --no-build"
|