#!/usr/bin/env bash # Restart the novel-app Flask server on 0.0.0.0:8091. # # Guarantees: # - PID file (/tmp/novel-app.pid) tracks the live server. # - Old server is killed before new one starts. # - Health check loops on /healthz up to 30s (1s interval). 启动失败立即报错. # - On failure: kill the failed new PID, print last 50 lines of /tmp/novel-app.log, exit 1. set -u set -o pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" APP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" PID_FILE="$APP_DIR/app.pid" LOG_FILE="/tmp/novel-app.log" HEALTHZ_URL="http://127.0.0.1:8091/healthz" HEALTHZ_TIMEOUT_S=30 PYTHON_BIN="/usr/bin/python3" cd "$APP_DIR" export HOME=/home/yi log() { printf '[deploy] %s\n' "$*"; } fail() { log "ERROR: $*" log "----- last 50 lines of $LOG_FILE -----" tail -n 50 "$LOG_FILE" 2>/dev/null || log "(no log file)" exit 1 } # --- 1. Kill old server if PID is alive --- OLD_PID="" if [[ -f "$PID_FILE" ]]; then OLD_PID="$(cat "$PID_FILE" 2>/dev/null || true)" fi if [[ -n "$OLD_PID" ]] && kill -0 "$OLD_PID" 2>/dev/null; then log "stopping old server pid=$OLD_PID" kill "$OLD_PID" 2>/dev/null || true for _ in 1 2 3 4 5; do if ! kill -0 "$OLD_PID" 2>/dev/null; then break; fi sleep 1 done if kill -0 "$OLD_PID" 2>/dev/null; then log "old pid $OLD_PID did not exit, sending SIGKILL" kill -9 "$OLD_PID" 2>/dev/null || true fi fi # --- 2. Ensure DB schema exists --- "$PYTHON_BIN" scripts/init_db.py > /dev/null || fail "init_db failed" # --- 3. Start new server, record PID --- log "starting new server: $PYTHON_BIN app.py (port 8091)" setsid nohup "$PYTHON_BIN" app.py > "$LOG_FILE" 2>&1 & NEW_PID=$! echo "$NEW_PID" > "$PID_FILE" log "new pid=$NEW_PID" # --- 4. Health check loop --- healthz_ok=0 for ((i=1; i<=HEALTHZ_TIMEOUT_S; i++)); do if ! kill -0 "$NEW_PID" 2>/dev/null; then fail "server process $NEW_PID died during startup" fi code="$(curl -sS -o /dev/null -w '%{http_code}' --max-time 2 "$HEALTHZ_URL" 2>/dev/null || echo '000')" if [[ "$code" == "200" ]]; then healthz_ok=1 log "healthz OK after ${i}s" break fi sleep 1 done if [[ "$healthz_ok" -ne 1 ]]; then kill "$NEW_PID" 2>/dev/null || true sleep 1 kill -9 "$NEW_PID" 2>/dev/null || true rm -f "$PID_FILE" fail "deploy failed; health check timed out" fi log "deploy succeeded pid=$NEW_PID" curl -sS -o /dev/null -w 'local:%{http_code}\n' "$HEALTHZ_URL"