新增MySQL备份恢复脚本并完成演练

This commit is contained in:
hello-dd-code
2026-02-28 16:39:53 +08:00
parent 5666dc61a0
commit 016c47ba75
4 changed files with 180 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail
# 支持两种模式:
# 1) 本机 mysql/mysqldump
# MYSQL_HOST MYSQL_PORT MYSQL_USER MYSQL_PASSWORD MYSQL_DATABASE
# 2) 容器内执行(推荐在无本地 mysql 客户端时使用):
# MYSQL_CONTAINER=<container_name>
MYSQL_HOST="${MYSQL_HOST:-127.0.0.1}"
MYSQL_PORT="${MYSQL_PORT:-3306}"
MYSQL_USER="${MYSQL_USER:-root}"
MYSQL_PASSWORD="${MYSQL_PASSWORD:-}"
MYSQL_DATABASE="${MYSQL_DATABASE:-wx_service}"
MYSQL_CONTAINER="${MYSQL_CONTAINER:-}"
BACKUP_DIR="${BACKUP_DIR:-/var/backups/wx_service}"
KEEP_DAYS="${KEEP_DAYS:-7}"
OPS_ALERT_WEBHOOK="${OPS_ALERT_WEBHOOK:-}"
ALERT_TITLE="${ALERT_TITLE:-[wx_service] 数据备份失败}"
send_alert() {
local message="$1"
if [[ -z "${OPS_ALERT_WEBHOOK}" ]]; then
echo "ALERT: ${message}" >&2
return
fi
curl -fsS -X POST "${OPS_ALERT_WEBHOOK}" \
-H "Content-Type: application/json" \
-d "{\"title\":\"${ALERT_TITLE}\",\"message\":\"${message}\"}" >/dev/null || true
}
dump_cmd() {
if [[ -n "${MYSQL_CONTAINER}" ]]; then
if [[ -n "${MYSQL_PASSWORD}" ]]; then
docker exec "${MYSQL_CONTAINER}" mysqldump -h127.0.0.1 -P"${MYSQL_PORT}" -u"${MYSQL_USER}" "-p${MYSQL_PASSWORD}" --single-transaction --quick --set-gtid-purged=OFF "${MYSQL_DATABASE}"
else
docker exec "${MYSQL_CONTAINER}" mysqldump -h127.0.0.1 -P"${MYSQL_PORT}" -u"${MYSQL_USER}" --single-transaction --quick --set-gtid-purged=OFF "${MYSQL_DATABASE}"
fi
return
fi
if [[ -n "${MYSQL_PASSWORD}" ]]; then
mysqldump -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" -u"${MYSQL_USER}" "-p${MYSQL_PASSWORD}" --single-transaction --quick --set-gtid-purged=OFF "${MYSQL_DATABASE}"
else
mysqldump -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" -u"${MYSQL_USER}" --single-transaction --quick --set-gtid-purged=OFF "${MYSQL_DATABASE}"
fi
}
mkdir -p "${BACKUP_DIR}"
timestamp="$(date +%Y%m%d_%H%M%S)"
outfile="${BACKUP_DIR}/${MYSQL_DATABASE}_${timestamp}.sql.gz"
if ! dump_cmd | gzip -9 > "${outfile}"; then
send_alert "MySQL 备份失败,数据库=${MYSQL_DATABASE}"
exit 1
fi
find "${BACKUP_DIR}" -type f -name "${MYSQL_DATABASE}_*.sql.gz" -mtime +"${KEEP_DAYS}" -delete || true
echo "backup created: ${outfile}"
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
set -euo pipefail
# 用法:
# CONFIRM_RESTORE=1 ./scripts/ops/restore_mysql.sh /path/to/backup.sql.gz
#
# 支持两种模式:
# 1) 本机 mysql 客户端
# 2) MYSQL_CONTAINER=<container_name>(在容器内执行 mysql
if [[ "${CONFIRM_RESTORE:-0}" != "1" ]]; then
echo "restore blocked: set CONFIRM_RESTORE=1 to continue" >&2
exit 1
fi
if [[ $# -lt 1 ]]; then
echo "usage: $0 <backup.sql|backup.sql.gz>" >&2
exit 1
fi
backup_file="$1"
if [[ ! -f "${backup_file}" ]]; then
echo "backup file not found: ${backup_file}" >&2
exit 1
fi
MYSQL_HOST="${MYSQL_HOST:-127.0.0.1}"
MYSQL_PORT="${MYSQL_PORT:-3306}"
MYSQL_USER="${MYSQL_USER:-root}"
MYSQL_PASSWORD="${MYSQL_PASSWORD:-}"
MYSQL_DATABASE="${MYSQL_DATABASE:-wx_service}"
MYSQL_CONTAINER="${MYSQL_CONTAINER:-}"
run_mysql() {
if [[ -n "${MYSQL_CONTAINER}" ]]; then
if [[ -n "${MYSQL_PASSWORD}" ]]; then
docker exec -i "${MYSQL_CONTAINER}" mysql -h127.0.0.1 -P"${MYSQL_PORT}" -u"${MYSQL_USER}" "-p${MYSQL_PASSWORD}" "${MYSQL_DATABASE}"
else
docker exec -i "${MYSQL_CONTAINER}" mysql -h127.0.0.1 -P"${MYSQL_PORT}" -u"${MYSQL_USER}" "${MYSQL_DATABASE}"
fi
return
fi
if [[ -n "${MYSQL_PASSWORD}" ]]; then
mysql -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" -u"${MYSQL_USER}" "-p${MYSQL_PASSWORD}" "${MYSQL_DATABASE}"
else
mysql -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" -u"${MYSQL_USER}" "${MYSQL_DATABASE}"
fi
}
if [[ "${backup_file}" == *.gz ]]; then
zcat "${backup_file}" | run_mysql
else
cat "${backup_file}" | run_mysql
fi
echo "restore completed: ${backup_file}"