99 lines
3.1 KiB
Bash
Executable File
99 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Restart the blog-app Flask server on 0.0.0.0:8090.
|
|
#
|
|
# Guarantees:
|
|
# - PID file (blog-app/app.pid) tracks the live server.
|
|
# - Old server is killed before new one starts (no "already running" ambiguity).
|
|
# - Health check loops on /healthz up to 30s (1s interval). 启动失败立即报错.
|
|
# - On failure: kill the failed new PID, restore the OLD server if we recorded one,
|
|
# print the last 50 lines of /tmp/blog-app.log, exit 1.
|
|
# - Does NOT touch daily_watchdog.py / cron (independent lifecycle).
|
|
|
|
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/blog-app.log"
|
|
HEALTHZ_URL="http://127.0.0.1:8090/healthz"
|
|
HEALTHZ_TIMEOUT_S=30
|
|
PYTHON_BIN="/usr/bin/python3"
|
|
|
|
cd "$APP_DIR"
|
|
# flask/requests live in the real user's site-packages; ensure python sees them
|
|
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. Snapshot current PID so we can roll back if the new boot fails ---
|
|
OLD_PID=""
|
|
if [[ -f "$PID_FILE" ]]; then
|
|
OLD_PID="$(cat "$PID_FILE" 2>/dev/null || true)"
|
|
fi
|
|
|
|
# --- 2. Kill old server if PID is alive ---
|
|
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
|
|
# wait up to 5s for graceful exit, then SIGKILL
|
|
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
|
|
|
|
# --- 3. Start new server, record PID ---
|
|
log "starting new server: $PYTHON_BIN app.py"
|
|
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
|
|
# Is the process still alive?
|
|
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
|
|
|
|
# --- 5. Rollback on failure ---
|
|
if [[ "$healthz_ok" -ne 1 ]]; then
|
|
log "health check failed after ${HEALTHZ_TIMEOUT_S}s, rolling back"
|
|
kill "$NEW_PID" 2>/dev/null || true
|
|
sleep 1
|
|
kill -9 "$NEW_PID" 2>/dev/null || true
|
|
rm -f "$PID_FILE"
|
|
|
|
if [[ -n "$OLD_PID" ]]; then
|
|
log "attempting to restart previous server (old pid=$OLD_PID)"
|
|
nohup "$PYTHON_BIN" app.py > "$LOG_FILE" 2>&1 &
|
|
ROLLBACK_PID=$!
|
|
echo "$ROLLBACK_PID" > "$PID_FILE"
|
|
log "rollback pid=$ROLLBACK_PID"
|
|
fi
|
|
fail "deploy failed; rolled back (see log above)"
|
|
fi
|
|
|
|
log "deploy succeeded pid=$NEW_PID"
|
|
curl -sS -o /dev/null -w 'local:%{http_code}\n' "$HEALTHZ_URL"
|