backups
This commit is contained in:
@@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
|
||||||
|
OUTPUT_FILE=""
|
||||||
|
COMPRESS=1
|
||||||
|
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [--output FILE] [--no-compress]
|
||||||
|
|
||||||
|
Exports all AzerothCore databases from the running ac-database container
|
||||||
|
into a single dump file suitable for migration to another server.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--output FILE Output file path
|
||||||
|
(default: ./backups/YYYY-MM-DD_HH-MM-SS.sql.gz)
|
||||||
|
--no-compress Write plain .sql instead of .sql.gz
|
||||||
|
-h, --help Show this help
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0")
|
||||||
|
$(basename "$0") --output /mnt/backup/moonwell.sql.gz
|
||||||
|
$(basename "$0") --no-compress --output /tmp/dump.sql
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
log() { printf '[db-export] %s\n' "$*"; }
|
||||||
|
die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
require_running_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
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── argument parsing ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
while (($#)); do
|
||||||
|
case "$1" in
|
||||||
|
--output) OUTPUT_FILE="$2"; shift ;;
|
||||||
|
--no-compress) COMPRESS=0 ;;
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
*) printf 'Unknown option: %s\n\n' "$1" >&2; usage >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# ── main ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
require_running_db
|
||||||
|
|
||||||
|
if [[ -z "$OUTPUT_FILE" ]]; then
|
||||||
|
mkdir -p "$ROOT_DIR/backups"
|
||||||
|
timestamp="$(date '+%Y-%m-%d_%H-%M-%S')"
|
||||||
|
if [[ "$COMPRESS" -eq 1 ]]; then
|
||||||
|
OUTPUT_FILE="$ROOT_DIR/backups/${timestamp}.sql.gz"
|
||||||
|
else
|
||||||
|
OUTPUT_FILE="$ROOT_DIR/backups/${timestamp}.sql"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$OUTPUT_FILE")"
|
||||||
|
|
||||||
|
log "exporting all databases → $OUTPUT_FILE"
|
||||||
|
log "this may take a few minutes for large worlds..."
|
||||||
|
|
||||||
|
if [[ "$COMPRESS" -eq 1 ]]; then
|
||||||
|
docker compose exec -T ac-database bash -lc \
|
||||||
|
"mysqldump -uroot -p\"\$MYSQL_ROOT_PASSWORD\" \
|
||||||
|
--all-databases \
|
||||||
|
--add-drop-database \
|
||||||
|
--single-transaction \
|
||||||
|
--quick \
|
||||||
|
--routines \
|
||||||
|
--triggers \
|
||||||
|
--events" \
|
||||||
|
| gzip -6 > "$OUTPUT_FILE"
|
||||||
|
else
|
||||||
|
docker compose exec -T ac-database bash -lc \
|
||||||
|
"mysqldump -uroot -p\"\$MYSQL_ROOT_PASSWORD\" \
|
||||||
|
--all-databases \
|
||||||
|
--add-drop-database \
|
||||||
|
--single-transaction \
|
||||||
|
--quick \
|
||||||
|
--routines \
|
||||||
|
--triggers \
|
||||||
|
--events" \
|
||||||
|
> "$OUTPUT_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "done: $OUTPUT_FILE ($(du -sh "$OUTPUT_FILE" | cut -f1))"
|
||||||
|
log ""
|
||||||
|
log "to restore on the new server:"
|
||||||
|
if [[ "$OUTPUT_FILE" == *.gz ]]; then
|
||||||
|
log " bash scripts/db-import.sh --from $OUTPUT_FILE"
|
||||||
|
else
|
||||||
|
log " bash scripts/db-import.sh --from $OUTPUT_FILE"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
|
||||||
|
DUMP_FILE=""
|
||||||
|
TARGET_HOST="127.0.0.1"
|
||||||
|
TARGET_PORT="3306"
|
||||||
|
TARGET_USER="root"
|
||||||
|
TARGET_PASSWORD=""
|
||||||
|
DRY_RUN=0
|
||||||
|
FORCE=0
|
||||||
|
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use password from .env if not overridden
|
||||||
|
TARGET_PASSWORD="${TARGET_PASSWORD:-${DOCKER_DB_ROOT_PASSWORD:-}}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") --from FILE [options]
|
||||||
|
|
||||||
|
Restores a full database dump (produced by db-export.sh) into a MySQL instance.
|
||||||
|
Works with both the local Docker container and a remote MySQL server.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--from FILE Dump file to restore (.sql or .sql.gz) (required)
|
||||||
|
--host HOST Target MySQL host (default: 127.0.0.1)
|
||||||
|
--port PORT Target MySQL port (default: 3306)
|
||||||
|
--user USER Target MySQL user (default: root)
|
||||||
|
--password PASS Target MySQL password (default: from .env DOCKER_DB_ROOT_PASSWORD)
|
||||||
|
--dry-run Show what would happen without executing
|
||||||
|
--force Skip the confirmation prompt
|
||||||
|
-h, --help Show this help
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
# Restore into local Docker container (new server, container must be running)
|
||||||
|
$(basename "$0") --from backups/2025-01-01_12-00-00.sql.gz
|
||||||
|
|
||||||
|
# Restore into a remote MySQL server
|
||||||
|
$(basename "$0") --from backups/dump.sql.gz \\
|
||||||
|
--host db.example.com --port 3306 \\
|
||||||
|
--user root --password secret
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
log() { printf '[db-import] %s\n' "$*"; }
|
||||||
|
die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
mysql_cmd() {
|
||||||
|
mysql \
|
||||||
|
--host="$TARGET_HOST" \
|
||||||
|
--port="$TARGET_PORT" \
|
||||||
|
--user="$TARGET_USER" \
|
||||||
|
--password="$TARGET_PASSWORD" \
|
||||||
|
--connect-timeout=10 \
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── argument parsing ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
while (($#)); do
|
||||||
|
case "$1" in
|
||||||
|
--from) DUMP_FILE="$2"; shift ;;
|
||||||
|
--host) TARGET_HOST="$2"; shift ;;
|
||||||
|
--port) TARGET_PORT="$2"; shift ;;
|
||||||
|
--user) TARGET_USER="$2"; shift ;;
|
||||||
|
--password) TARGET_PASSWORD="$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"
|
||||||
|
[[ -z "$TARGET_PASSWORD" ]] && die "no password set — use --password or set DOCKER_DB_ROOT_PASSWORD in .env"
|
||||||
|
|
||||||
|
if ! command -v mysql >/dev/null 2>&1; then
|
||||||
|
die "'mysql' client not found. Install it: apt install mysql-client or brew install mysql-client"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
# ── preview ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
file_size="$(du -sh "$DUMP_FILE" | cut -f1)"
|
||||||
|
|
||||||
|
printf '\nMigration plan:\n'
|
||||||
|
printf ' Source file : %s (%s)\n' "$DUMP_FILE" "$file_size"
|
||||||
|
printf ' Target host : %s:%s\n' "$TARGET_HOST" "$TARGET_PORT"
|
||||||
|
printf ' Target user : %s\n\n' "$TARGET_USER"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# ── connectivity check ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
log "checking connection to ${TARGET_HOST}:${TARGET_PORT}..."
|
||||||
|
if ! mysql_cmd --execute="SELECT 1;" >/dev/null 2>&1; then
|
||||||
|
die "cannot connect to MySQL at ${TARGET_HOST}:${TARGET_PORT} as ${TARGET_USER}"
|
||||||
|
fi
|
||||||
|
log "connection OK"
|
||||||
|
|
||||||
|
# ── import ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
log "restoring $DUMP_FILE → ${TARGET_HOST}:${TARGET_PORT}..."
|
||||||
|
log "this may take several minutes..."
|
||||||
|
|
||||||
|
if [[ "$DUMP_FILE" == *.gz ]]; then
|
||||||
|
zcat "$DUMP_FILE" | mysql_cmd
|
||||||
|
else
|
||||||
|
mysql_cmd < "$DUMP_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "import complete"
|
||||||
|
log ""
|
||||||
|
log "next steps on the new server:"
|
||||||
|
log " 1. Update realmlist: bash scripts/sync-realmlist.sh"
|
||||||
|
log " 2. Start the server: bash scripts/prod-deploy.sh --no-build"
|
||||||
Reference in New Issue
Block a user