#!/usr/bin/env bash # 服务器上拉代码并重启 PM2. # 用法(/opt/crypto_okx 下 root): # bash deploy/pull_and_restart.sh # bash deploy/pull_and_restart.sh --dry-run set -e set -u if [ -n "${BASH_VERSION:-}" ]; then set -o pipefail fi REPO="${REPO:-/opt/crypto_okx}" PM2_APP_NAME="${PM2_APP_NAME:-crypto_okx}" DRY=0 if [[ "${1:-}" == "--dry-run" ]]; then DRY=1 echo "(dry-run mode)" fi pm2_has_app() { local name="$1" if ! command -v pm2 >/dev/null 2>&1; then return 1 fi if command -v python3 >/dev/null 2>&1; then pm2 jlist 2>/dev/null | python3 -c ' import json,sys name=sys.argv[1] try: apps=json.load(sys.stdin) except Exception: sys.exit(1) sys.exit(0 if any(isinstance(a,dict) and a.get("name")==name for a in (apps or [])) else 1) ' "${name}" return $? fi pm2 describe "${name}" 2>/dev/null | grep -qE 'status[[:space:]]*[|:]' } read_port() { local env_file="${REPO}/.env" local port="5004" if [[ -f "${env_file}" ]]; then local line line="$(grep -E '^[[:space:]]*APP_PORT=' "${env_file}" | tail -n1 || true)" if [[ -n "${line}" ]]; then port="${line#*=}" port="$(echo "${port}" | tr -d '"' | tr -d "'" | xargs)" fi fi echo "${port:-5004}" } wait_http_ready() { local port="$1" local url="http://127.0.0.1:${port}/" local i code echo ">>> 等待 HTTP 就绪 ${url} (最多 30s)" for i in $(seq 1 30); do code="$(curl -sS -o /dev/null -w '%{http_code}' --connect-timeout 2 --max-time 3 "${url}" 2>/dev/null || echo "000")" if [[ "${code}" == "200" || "${code}" == "302" || "${code}" == "301" || "${code}" == "401" || "${code}" == "403" ]]; then echo ">>> HTTP OK (${code}) after ${i}s" return 0 fi # 进程挂了就别空等 if ! pm2_has_app "${PM2_APP_NAME}"; then echo ">>> PM2 进程已消失" >&2 return 1 fi sleep 1 done echo ">>> HTTP 仍未就绪 (最后 code=${code:-000})" >&2 echo ">>> 请查看: pm2 logs ${PM2_APP_NAME} --lines 50" >&2 return 1 } cd "${REPO}" echo ">>> git pull" git pull if [[ "${DRY}" -eq 1 ]]; then echo "(dry-run, skip pm2 restart)" exit 0 fi if ! command -v pm2 >/dev/null 2>&1; then echo "warn: 未安装 pm2" >&2 exit 1 fi if [[ ! -f ecosystem.config.cjs ]]; then echo "error: 缺少 ecosystem.config.cjs" >&2 exit 1 fi if pm2_has_app "${PM2_APP_NAME}"; then echo ">>> pm2 restart ${PM2_APP_NAME} --update-env" pm2 restart "${PM2_APP_NAME}" --update-env else echo ">>> 未注册 ${PM2_APP_NAME},执行 pm2 start ecosystem.config.cjs" pm2 start ecosystem.config.cjs fi port="$(read_port)" wait_http_ready "${port}" || true echo "done"