47 lines
1.9 KiB
Bash
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"
|