@@ -10,10 +10,12 @@ ENV_FILE="${ENV_FILE:-$PROJECT_DIR/.env.production}"
|
||||
SERVICE_NAME="${SERVICE_NAME:-hulumath-web}"
|
||||
BACKUP_DIR="${BACKUP_DIR:-/www/backup/hulumath}"
|
||||
MYSQLDUMP_BIN="${MYSQLDUMP_BIN:-}"
|
||||
MYSQL_CONTAINER="${MYSQL_CONTAINER:-}"
|
||||
PREVIOUS_REVISION="${PREVIOUS_REVISION:-}"
|
||||
HEALTH_HOST="${DEPLOY_HEALTH_HOST:-}"
|
||||
ROLLBACK_ENABLED=0
|
||||
MYSQL_CREDENTIALS_FILE=""
|
||||
MYSQL_CONTAINER_CREDENTIALS_PATH=""
|
||||
|
||||
log() {
|
||||
printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
|
||||
@@ -39,6 +41,10 @@ DEPLOY_OWNER="$(id -un):$(id -gn)"
|
||||
rollback_application() {
|
||||
local exit_code="${1:-$?}"
|
||||
trap - ERR
|
||||
if [ -n "$MYSQL_CONTAINER_CREDENTIALS_PATH" ] && [ -n "$MYSQL_CONTAINER" ]; then
|
||||
docker exec "$MYSQL_CONTAINER" rm -f "$MYSQL_CONTAINER_CREDENTIALS_PATH" \
|
||||
>/dev/null 2>&1 || true
|
||||
fi
|
||||
if [ -n "$MYSQL_CREDENTIALS_FILE" ]; then
|
||||
rm -f "$MYSQL_CREDENTIALS_FILE"
|
||||
fi
|
||||
@@ -124,20 +130,32 @@ $SUDO chown -R "$DEPLOY_OWNER" "$VENV_DIR"
|
||||
"$VENV_DIR/bin/pip" install --disable-pip-version-check -r requirements.txt
|
||||
|
||||
log "备份 MySQL"
|
||||
if [ -z "$MYSQLDUMP_BIN" ]; then
|
||||
MYSQLDUMP_BIN="$(command -v mysqldump || true)"
|
||||
if [ -n "$MYSQL_CONTAINER" ]; then
|
||||
command -v docker >/dev/null 2>&1 || fail "配置了 MYSQL_CONTAINER,但服务器没有 docker 命令"
|
||||
docker inspect "$MYSQL_CONTAINER" >/dev/null 2>&1 \
|
||||
|| fail "MySQL 容器不存在: $MYSQL_CONTAINER"
|
||||
docker exec "$MYSQL_CONTAINER" mysqldump --version \
|
||||
| grep -Eq 'Distrib 8\.' \
|
||||
|| fail "容器内 mysqldump 不是 MySQL 8: $MYSQL_CONTAINER"
|
||||
else
|
||||
if [ -z "$MYSQLDUMP_BIN" ]; then
|
||||
MYSQLDUMP_BIN="$(command -v mysqldump || true)"
|
||||
fi
|
||||
if [ -z "$MYSQLDUMP_BIN" ]; then
|
||||
for candidate in \
|
||||
/www/server/mysql/bin/mysqldump \
|
||||
/usr/bin/mysqldump; do
|
||||
if [ -x "$candidate" ]; then
|
||||
MYSQLDUMP_BIN="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
[ -x "$MYSQLDUMP_BIN" ] \
|
||||
|| fail "未找到 mysqldump;Docker MySQL 请设置 MYSQL_CONTAINER"
|
||||
"$MYSQLDUMP_BIN" --version | grep -Eq 'Distrib 8\.' \
|
||||
|| fail "宿主机 mysqldump 不是 MySQL 8;请设置 MYSQL_CONTAINER 使用容器内客户端"
|
||||
fi
|
||||
if [ -z "$MYSQLDUMP_BIN" ]; then
|
||||
for candidate in \
|
||||
/www/server/mysql/bin/mysqldump \
|
||||
/usr/bin/mysqldump; do
|
||||
if [ -x "$candidate" ]; then
|
||||
MYSQLDUMP_BIN="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
[ -x "$MYSQLDUMP_BIN" ] || fail "未找到 mysqldump;可通过 MYSQLDUMP_BIN 指定客户端路径"
|
||||
$SUDO mkdir -p "$BACKUP_DIR"
|
||||
$SUDO chown "$(id -un):$(id -gn)" "$BACKUP_DIR"
|
||||
BACKUP_FILE="$BACKUP_DIR/hulumath_$(date '+%Y%m%d_%H%M%S').sql.gz"
|
||||
@@ -167,24 +185,41 @@ def quote(value):
|
||||
|
||||
with open(sys.argv[1], "w", encoding="utf-8") as target:
|
||||
target.write("[client]\n")
|
||||
target.write(f"host={quote(values['host'])}\n")
|
||||
target.write(f"port={values['port']}\n")
|
||||
if not os.environ.get("MYSQL_CONTAINER"):
|
||||
target.write(f"host={quote(values['host'])}\n")
|
||||
target.write(f"port={values['port']}\n")
|
||||
target.write(f"user={quote(values['user'])}\n")
|
||||
target.write(f"password={quote(values['password'])}\n")
|
||||
target.write("default-character-set=utf8mb4\n")
|
||||
print(database)
|
||||
PY
|
||||
)"
|
||||
"$MYSQLDUMP_BIN" \
|
||||
--defaults-extra-file="$MYSQL_CREDENTIALS_FILE" \
|
||||
--single-transaction \
|
||||
--quick \
|
||||
--routines \
|
||||
--triggers \
|
||||
--events \
|
||||
--hex-blob \
|
||||
--set-gtid-purged=OFF \
|
||||
"$MYSQL_DATABASE_NAME" | gzip -c > "$BACKUP_FILE"
|
||||
if [ -n "$MYSQL_CONTAINER" ]; then
|
||||
MYSQL_CONTAINER_CREDENTIALS_PATH="/tmp/hulumath-dump-$$.cnf"
|
||||
docker cp "$MYSQL_CREDENTIALS_FILE" \
|
||||
"$MYSQL_CONTAINER:$MYSQL_CONTAINER_CREDENTIALS_PATH"
|
||||
docker exec "$MYSQL_CONTAINER" mysqldump \
|
||||
--defaults-extra-file="$MYSQL_CONTAINER_CREDENTIALS_PATH" \
|
||||
--single-transaction \
|
||||
--quick \
|
||||
--triggers \
|
||||
--hex-blob \
|
||||
--no-tablespaces \
|
||||
--set-gtid-purged=OFF \
|
||||
"$MYSQL_DATABASE_NAME" | gzip -c > "$BACKUP_FILE"
|
||||
docker exec "$MYSQL_CONTAINER" rm -f "$MYSQL_CONTAINER_CREDENTIALS_PATH"
|
||||
MYSQL_CONTAINER_CREDENTIALS_PATH=""
|
||||
else
|
||||
"$MYSQLDUMP_BIN" \
|
||||
--defaults-extra-file="$MYSQL_CREDENTIALS_FILE" \
|
||||
--single-transaction \
|
||||
--quick \
|
||||
--triggers \
|
||||
--hex-blob \
|
||||
--no-tablespaces \
|
||||
--set-gtid-purged=OFF \
|
||||
"$MYSQL_DATABASE_NAME" | gzip -c > "$BACKUP_FILE"
|
||||
fi
|
||||
rm -f "$MYSQL_CREDENTIALS_FILE"
|
||||
MYSQL_CREDENTIALS_FILE=""
|
||||
test -s "$BACKUP_FILE" || fail "数据库备份为空: $BACKUP_FILE"
|
||||
|
||||
Reference in New Issue
Block a user