#!/usr/bin/env bash # 同步 API 环境变量到服务器 # 用法: deploy/sync-api-env.sh staging|production set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" ENV_FILE="$REPO_ROOT/deploy/deploy.env" DEPLOY_HOST="" DEPLOY_USER="root" DEPLOY_PORT="22" DEPLOY_SSH_KEY="" APP_ROOT="/opt/dukang" STAGING_APP_ROOT="/opt/dukang-staging" PROD_APP_ROOT="/opt/dukang" TARGET="${1:-}" case "$TARGET" in staging|stage|test) TARGET=staging SRC_ENV="$REPO_ROOT/server/dukang-api/.env.staging" REMOTE_NAME=".env.staging" PM2_NAME=dukang-stg-api HEALTH_PORT=8190 ;; production|prod) TARGET=production SRC_ENV="$REPO_ROOT/server/dukang-api/.env.production" REMOTE_NAME=".env.production" PM2_NAME=dukang-api HEALTH_PORT=8090 ;; development|dev) echo "错误: development 仅用于本地开发,请使用 .env,不同步到服务器" >&2 exit 1 ;; *) echo "用法: $0 staging|production" >&2 exit 1 ;; esac if [[ -f "$ENV_FILE" ]]; then # shellcheck disable=SC1090 source "$ENV_FILE" fi if [[ "$TARGET" == "staging" ]]; then APP_ROOT="${STAGING_APP_ROOT:-/opt/dukang-staging}" else APP_ROOT="${PROD_APP_ROOT:-/opt/dukang}" fi if [[ ! -f "$SRC_ENV" ]]; then echo "错误: 未找到 $SRC_ENV(可从 ${SRC_ENV}.example 复制)" >&2 exit 1 fi if [[ -z "$DEPLOY_HOST" ]]; then echo "错误: 未配置 DEPLOY_HOST(deploy/deploy.env)" >&2 exit 1 fi SSH_OPTS=(-o "StrictHostKeyChecking=accept-new" -p "$DEPLOY_PORT") SCP_OPTS=(-o "StrictHostKeyChecking=accept-new" -P "$DEPLOY_PORT") [[ -n "$DEPLOY_SSH_KEY" ]] && SSH_OPTS+=(-i "$DEPLOY_SSH_KEY") && SCP_OPTS+=(-i "$DEPLOY_SSH_KEY") REMOTE="${DEPLOY_USER}@${DEPLOY_HOST}" echo "==> 同步 $TARGET 环境到 $REMOTE:$APP_ROOT/server/dukang-api/$REMOTE_NAME" scp "${SCP_OPTS[@]}" "$SRC_ENV" "$REMOTE:$APP_ROOT/server/dukang-api/$REMOTE_NAME" ssh "${SSH_OPTS[@]}" "$REMOTE" \ "pm2 restart $PM2_NAME && sleep 2 && curl -sf -o /dev/null -w 'api-health:%{http_code}\n' http://127.0.0.1:${HEALTH_PORT}/api/v1/health" echo "==> 完成"