重写在线备份链路
This commit is contained in:
+72
-14
@@ -146,23 +146,28 @@ validate_env() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local app_env caddy_domain caddy_email mysql_dsn redis_addr storage_endpoint backend_uid backend_gid
|
||||
local minio_root_user minio_root_password storage_access_key_id storage_secret_access_key
|
||||
local app_env caddy_domain caddy_email mysql_dsn redis_addr storage_endpoint backend_uid backend_gid backup_dir backup_restore_dir backup_oss_uri backup_user
|
||||
app_env="$(require_env APP_ENV)"
|
||||
caddy_domain="$(require_env CADDY_DOMAIN)"
|
||||
caddy_email="$(require_env CADDY_EMAIL)"
|
||||
mysql_dsn="$(require_env MYSQL_DSN)"
|
||||
redis_addr="$(require_env REDIS_ADDR)"
|
||||
storage_endpoint="$(require_env STORAGE_ENDPOINT)"
|
||||
require_env MYSQL_DATABASE >/dev/null
|
||||
local mysql_database
|
||||
mysql_database="$(require_env MYSQL_DATABASE)"
|
||||
require_env MYSQL_ROOT_PASSWORD >/dev/null
|
||||
require_env MYSQL_USER >/dev/null
|
||||
require_env MYSQL_PASSWORD >/dev/null
|
||||
require_env JWT_SECRET >/dev/null
|
||||
minio_root_user="$(require_env MINIO_ROOT_USER)"
|
||||
minio_root_password="$(require_env MINIO_ROOT_PASSWORD)"
|
||||
storage_access_key_id="$(require_env STORAGE_ACCESS_KEY_ID)"
|
||||
storage_secret_access_key="$(require_env STORAGE_SECRET_ACCESS_KEY)"
|
||||
require_env STORAGE_ACCESS_KEY_ID >/dev/null
|
||||
require_env STORAGE_SECRET_ACCESS_KEY >/dev/null
|
||||
backup_dir="$(require_env BACKUP_DIR)"
|
||||
backup_restore_dir="$(require_env BACKUP_RESTORE_DIR)"
|
||||
backup_oss_uri="$(require_env BACKUP_OSS_URI)"
|
||||
require_env BACKUP_PASSPHRASE >/dev/null
|
||||
require_env BACKUP_KMS_KEY_ID >/dev/null
|
||||
backup_user="$(require_env BACKUP_MYSQL_USER)"
|
||||
require_env BACKUP_MYSQL_PASSWORD >/dev/null
|
||||
backend_uid="$(require_env BACKEND_UID)"
|
||||
backend_gid="$(require_env BACKEND_GID)"
|
||||
|
||||
@@ -197,14 +202,36 @@ validate_env() {
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${storage_endpoint}" == *"127.0.0.1"* || "${storage_endpoint}" == *"localhost"* ]]; then
|
||||
log_error "STORAGE_ENDPOINT 仍指向本机,请改为 http://minio:9000"
|
||||
log_error "STORAGE_ENDPOINT 仍指向本机,请改为阿里云 OSS Endpoint(如 https://oss-cn-hangzhou.aliyuncs.com)"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${storage_endpoint}" == "http://minio:9000" || "${storage_endpoint}" == "minio:9000" ]]; then
|
||||
if [[ "${storage_access_key_id}" != "${minio_root_user}" || "${storage_secret_access_key}" != "${minio_root_password}" ]]; then
|
||||
log_error "使用内置 MinIO 时,STORAGE_ACCESS_KEY_ID/SECRET_ACCESS_KEY 必须和 MINIO_ROOT_USER/ROOT_PASSWORD 保持一致"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${storage_endpoint}" == *"minio"* ]]; then
|
||||
log_error "STORAGE_ENDPOINT 仍指向已下线的 MinIO,请改为阿里云 OSS Endpoint"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${storage_endpoint}" =~ ^https://oss-[A-Za-z0-9-]+\.aliyuncs\.com/?$ ]]; then
|
||||
log_error "STORAGE_ENDPOINT 必须是阿里云 OSS HTTPS Endpoint,当前值:${storage_endpoint}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${backup_dir}" != /data/* || "${backup_dir}" == "/data" ]]; then
|
||||
log_error "BACKUP_DIR 必须是 /data 之下的具体绝对路径,当前值:${backup_dir}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${backup_restore_dir}" != /data/* || "${backup_restore_dir}" == "/data" || "${backup_restore_dir}" == "${backup_dir}" ]]; then
|
||||
log_error "BACKUP_RESTORE_DIR 必须是与 BACKUP_DIR 不同的 /data 子目录,当前值:${backup_restore_dir}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${backup_oss_uri}" =~ ^oss://[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then
|
||||
log_error "BACKUP_OSS_URI 必须是 oss://bucket 格式,当前值:${backup_oss_uri}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${backup_user}" =~ ^[A-Za-z0-9_]{1,32}$ ]]; then
|
||||
log_error "BACKUP_MYSQL_USER 只能包含字母、数字和下划线,长度不超过 32"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${mysql_database}" =~ ^[A-Za-z0-9_]+$ ]]; then
|
||||
log_error "MYSQL_DATABASE 只能包含字母、数字和下划线,当前值:${mysql_database}"
|
||||
exit 1
|
||||
fi
|
||||
if awk -F= '/^[A-Z0-9_]+=/{ if ($0 ~ /=(change-|保持你的|你的)/) found=1 } END { exit found ? 0 : 1 }' "${BACKEND_ENV}"; then
|
||||
log_error "backend/.env 里还有占位值,请先替换后再部署"
|
||||
@@ -407,6 +434,34 @@ mysql_root_exec() {
|
||||
compose exec -T mysql sh -c 'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysql -uroot "$@"' sh "$@"
|
||||
}
|
||||
|
||||
sql_string_literal() {
|
||||
local value="$1"
|
||||
value="${value//\\/\\\\}"
|
||||
value="${value//\'/\'\'}"
|
||||
printf '%s' "${value}"
|
||||
}
|
||||
|
||||
ensure_mysql_backup_user() {
|
||||
local database backup_user backup_password escaped_password
|
||||
database="$(require_env MYSQL_DATABASE)"
|
||||
backup_user="$(require_env BACKUP_MYSQL_USER)"
|
||||
backup_password="$(require_env BACKUP_MYSQL_PASSWORD)"
|
||||
escaped_password="$(sql_string_literal "${backup_password}")"
|
||||
unset backup_password
|
||||
|
||||
log "配置 MySQL 在线备份账号 ${backup_user}"
|
||||
printf "CREATE USER IF NOT EXISTS \`%s\`@'%%' IDENTIFIED BY '%s';\n" "${backup_user}" "${escaped_password}" |
|
||||
compose exec -T mysql sh -c 'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysql -uroot --protocol=socket'
|
||||
printf "ALTER USER \`%s\`@'%%' IDENTIFIED BY '%s';\n" "${backup_user}" "${escaped_password}" |
|
||||
compose exec -T mysql sh -c 'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysql -uroot --protocol=socket'
|
||||
printf "GRANT BACKUP_ADMIN, PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO \`%s\`@'%%';\n" "${backup_user}" |
|
||||
compose exec -T mysql sh -c 'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysql -uroot --protocol=socket'
|
||||
printf "GRANT SELECT ON performance_schema.log_status TO \`%s\`@'%%';\n" "${backup_user}" |
|
||||
compose exec -T mysql sh -c 'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysql -uroot --protocol=socket'
|
||||
printf "GRANT SELECT ON \`%s\`.* TO \`%s\`@'%%';\n" "${database}" "${backup_user}" |
|
||||
compose exec -T mysql sh -c 'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysql -uroot --protocol=socket'
|
||||
}
|
||||
|
||||
goose_dsn() {
|
||||
local dsn="$1"
|
||||
if [[ "${dsn}" != *"multiStatements="* ]]; then
|
||||
@@ -492,6 +547,9 @@ main() {
|
||||
cd "${ROOT_DIR}"
|
||||
need_cmd docker
|
||||
need_cmd curl
|
||||
need_cmd openssl
|
||||
need_cmd ossutil
|
||||
need_cmd flock
|
||||
validate_env
|
||||
export_caddy_env
|
||||
prepare_log_dir
|
||||
@@ -534,8 +592,8 @@ main() {
|
||||
|
||||
wait_service_healthy mysql "MySQL"
|
||||
wait_service_healthy redis "Redis"
|
||||
wait_service_healthy minio "MinIO"
|
||||
wait_service_healthy caddy "Caddy"
|
||||
ensure_mysql_backup_user
|
||||
reset_database
|
||||
run_migrations
|
||||
|
||||
|
||||
Reference in New Issue
Block a user