Files
lehuo/infra/ubuntu/scripts/restore.sh
T

47 lines
1.9 KiB
Bash

#!/usr/bin/env bash
set -Eeuo pipefail
# shellcheck source=lib.sh
source "$(dirname -- "${BASH_SOURCE[0]}")/lib.sh"
usage() {
echo '用法:restore.sh <backup.sql.gz> <target_database> --confirm <target_database> [env-file]'
}
backup="${1:-}"
target_database="${2:-}"
confirm_flag="${3:-}"
confirm_database="${4:-}"
env_file="${5:-/etc/lehuo/lehuo.env}"
[[ -n "$backup" && -n "$target_database" && "$confirm_flag" == '--confirm' && "$confirm_database" == "$target_database" ]] || {
usage >&2
exit 1
}
[[ "$target_database" =~ ^[A-Za-z0-9_]+$ ]] || { echo '目标数据库名无效。' >&2; exit 1; }
require_command docker
require_command gzip
require_command sha256sum
require_command realpath
require_env_file "$env_file"
backup_dir="$(realpath -m "$(env_value "$env_file" BACKUP_DIR)")"
backup_path="$(realpath -e "$backup")"
[[ "$backup_path" == "$backup_dir"/* ]] || { echo '备份文件必须位于 BACKUP_DIR。' >&2; exit 1; }
[[ -f "${backup_path}.sha256" ]] || { echo '缺少 SHA-256 校验文件。' >&2; exit 1; }
(cd -- "$backup_dir" && sha256sum -c "$(basename -- "${backup_path}.sha256")")
gzip -t "$backup_path"
production_database="$(env_value "$env_file" MYSQL_DATABASE)"
if [[ "$target_database" == "$production_database" && "${ALLOW_PRODUCTION_RESTORE:-}" != 'YES' ]]; then
echo '拒绝覆盖生产数据库。若已完成停机、审批和二次备份,请显式设置 ALLOW_PRODUCTION_RESTORE=YES。' >&2
exit 1
fi
compose "$env_file" exec -T -e RESTORE_DATABASE="$target_database" mysql sh -c \
'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" exec mysql -u root -e "CREATE DATABASE IF NOT EXISTS \`$RESTORE_DATABASE\` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci"'
gzip -dc "$backup_path" | compose "$env_file" exec -T -e RESTORE_DATABASE="$target_database" mysql sh -c \
'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" exec mysql -u root "$RESTORE_DATABASE"'
printf '恢复完成:%s → %s\n' "$backup_path" "$target_database"