97 lines
2.9 KiB
Bash
97 lines
2.9 KiB
Bash
#!/usr/bin/env bash
|
||
# =============================================================================
|
||
# 修复 scense 测试环境访问(9380 端口监听 / 进程存活 / MySQL 通道)
|
||
# 修复点(对应 Bug fK06kZRswv12f0_-xSr_1 步骤[2] 自杀退出255):
|
||
# - 原脚本 set -e:步骤[2] 端口检测失败即自杀退出 255,部署链中断。
|
||
# - 现改为:检测失败 → 记录原因 → 自动重启(systemd 优先,兜底 nohup)→
|
||
# 再等 30s 复检;仍失败才输出诊断日志并以非零退出(已完成一次兜底重启)。
|
||
# =============================================================================
|
||
set -uo pipefail
|
||
|
||
APP_NAME="scense"
|
||
APP_PORT="${SERVER_PORT:-9380}"
|
||
WORKDIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||
VENV_DIR="$WORKDIR/venv"
|
||
ENV_FILE="$WORKDIR/.env"
|
||
LOG="$WORKDIR/logs/scense.log"
|
||
|
||
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
|
||
|
||
[ -f "$ENV_FILE" ] && { set -a; . "$ENV_FILE"; set +a; }
|
||
|
||
# 步骤[1] 端口监听检测(/dev/tcp 无需额外工具)
|
||
check_port() {
|
||
(exec 3<>"/dev/tcp/127.0.0.1/$APP_PORT") 2>/dev/null && { exec 3>&- 3<&-; return 0; }
|
||
return 1
|
||
}
|
||
|
||
# 步骤[2] 进程存活检测
|
||
check_proc() {
|
||
pgrep -f "app/$APP_NAME.py" >/dev/null 2>&1
|
||
}
|
||
|
||
# 步骤[3] MySQL 通道检测
|
||
check_mysql() {
|
||
command -v mysql >/dev/null 2>&1 || return 1
|
||
mysql --host="${MYSQL_HOST:-127.0.0.1}" --port="${MYSQL_PORT:-3306}" \
|
||
--user="${MYSQL_USER:-root}" --password="${MYSQL_PASSWORD:-}" \
|
||
-e "SELECT 1" "${MYSQL_DATABASE:-scense}" >/dev/null 2>&1
|
||
}
|
||
|
||
# 重启兜底:systemd 优先,失败回退 nohup 直接拉起
|
||
restart_app() {
|
||
log "restart $APP_NAME ..."
|
||
if systemctl restart "$APP_NAME" 2>/dev/null; then
|
||
return 0
|
||
fi
|
||
pkill -f "app/$APP_NAME.py" 2>/dev/null || true
|
||
sleep 1
|
||
nohup "$VENV_DIR/bin/python" "$WORKDIR/app/$APP_NAME.py" >> "$LOG" 2>&1 &
|
||
return 0
|
||
}
|
||
|
||
main() {
|
||
local fix_count=0
|
||
|
||
if check_port; then
|
||
log "[1] port $APP_PORT listening"
|
||
else
|
||
log "[1] port $APP_PORT NOT listening -> need fix"
|
||
fix_count=$((fix_count+1))
|
||
fi
|
||
|
||
if check_proc; then
|
||
log "[2] process app/$APP_NAME.py running"
|
||
else
|
||
log "[2] process app/$APP_NAME.py NOT found -> need fix"
|
||
fix_count=$((fix_count+1))
|
||
fi
|
||
|
||
if check_mysql; then
|
||
log "[3] MySQL channel (${MYSQL_DATABASE:-scense}@${MYSQL_HOST:-127.0.0.1}) OK"
|
||
else
|
||
log "[3] MySQL channel unreachable -> need fix"
|
||
fix_count=$((fix_count+1))
|
||
fi
|
||
|
||
if [ "$fix_count" -gt 0 ]; then
|
||
log "detected $fix_count issue(s), restart app (bootstrap, no suicide exit)"
|
||
restart_app
|
||
for _ in $(seq 1 30); do
|
||
if check_port && check_proc; then
|
||
log "OK: $APP_NAME back on port $APP_PORT after restart"
|
||
exit 0
|
||
fi
|
||
sleep 1
|
||
done
|
||
log "WARN: $APP_NAME still not listening after restart; last log lines:"
|
||
tail -n 30 "$LOG" 2>/dev/null || true
|
||
exit 1
|
||
fi
|
||
|
||
log "OK: scense test env accessible (port=$APP_PORT)"
|
||
exit 0
|
||
}
|
||
|
||
main "$@"
|