- 重构隧道进程管理:将隧道启动从 entrypoint.sh 移至 docker-entrypoint.sh - 添加隧道自动重启机制:监控循环每5秒检查隧道进程状态,异常退出时自动重启 - 增强日志记录:隧道输出重定向至 /tmp/tunnel.log 便于问题排查 - 修复原始架构问题:解决 exec 替换进程导致后台隧道失去父进程监控的问题 - 优化清理逻辑:在信号处理和错误退出时正确清理隧道进程
181 lines
5.9 KiB
Bash
Executable File
181 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
||
# =============================================================================
|
||
# FA3 Datafetch 容器启动脚本
|
||
# 功能:启动后端 (FastAPI)、前端 (Next.js) 和隧道,处理进程管理
|
||
# =============================================================================
|
||
|
||
set -e
|
||
|
||
# 隧道重启函数
|
||
restart_tunnel() {
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 检测到隧道进程已停止,正在重启..."
|
||
if [ -n "$TUNNEL_PID" ]; then
|
||
kill "$TUNNEL_PID" 2>/dev/null || true
|
||
fi
|
||
|
||
# 确保环境变量存在
|
||
if [ -z "$SERVER_ADDRS" ] || [ -z "$SERVICE_ID" ] || [ -z "$LOCAL_PORT" ]; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:隧道环境变量缺失,无法重启"
|
||
return 1
|
||
fi
|
||
|
||
# 启动隧道
|
||
/usr/local/bin/portwardenc >/dev/null 2>&1 &
|
||
TUNNEL_PID=$!
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 隧道已重启,PID: $TUNNEL_PID"
|
||
|
||
# 保存 PID 到文件,方便监控
|
||
echo "$TUNNEL_PID" > /tmp/tunnel.pid 2>/dev/null || true
|
||
|
||
return 0
|
||
}
|
||
|
||
# 信号处理函数
|
||
cleanup() {
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 收到停止信号,正在关闭服务..."
|
||
if [ -n "$BACKEND_PID" ]; then
|
||
kill "$BACKEND_PID" 2>/dev/null || true
|
||
fi
|
||
if [ -n "$FRONTEND_PID" ]; then
|
||
kill "$FRONTEND_PID" 2>/dev/null || true
|
||
fi
|
||
if [ -n "$TUNNEL_PID" ]; then
|
||
kill "$TUNNEL_PID" 2>/dev/null || true
|
||
fi
|
||
# 等待进程结束
|
||
wait $BACKEND_PID $FRONTEND_PID $TUNNEL_PID 2>/dev/null || true
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 所有服务已停止"
|
||
exit 0
|
||
}
|
||
|
||
trap cleanup SIGTERM SIGINT
|
||
|
||
# =============================================================================
|
||
# 1. 启动后端服务
|
||
# =============================================================================
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动后端服务 (FastAPI on :8000)..."
|
||
|
||
cd /app/backend
|
||
export PYTHONPATH=/app:/app/backend
|
||
|
||
# 启动后端,日志输出到stdout
|
||
/app/.venv/bin/python -m uvicorn app.main:app \
|
||
--host 0.0.0.0 \
|
||
--port 8000 \
|
||
--access-log &
|
||
|
||
BACKEND_PID=$!
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 后端PID: $BACKEND_PID"
|
||
|
||
# 等待后端启动
|
||
sleep 3
|
||
|
||
# 检查后端是否启动成功
|
||
if ! kill -0 "$BACKEND_PID" 2>/dev/null; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:后端启动失败!"
|
||
exit 1
|
||
fi
|
||
|
||
# =============================================================================
|
||
# 2. 启动前端服务
|
||
# =============================================================================
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动前端服务 (Next.js on :3001)..."
|
||
|
||
cd /app/frontend
|
||
|
||
# 设置生产环境变量
|
||
export NODE_ENV=production
|
||
export PORT=3001
|
||
|
||
# 启动前端,日志输出到stdout
|
||
npm start &
|
||
|
||
FRONTEND_PID=$!
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 前端PID: $FRONTEND_PID"
|
||
|
||
# 等待前端启动
|
||
sleep 3
|
||
|
||
# 检查前端是否启动成功
|
||
if ! kill -0 "$FRONTEND_PID" 2>/dev/null; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:前端启动失败!"
|
||
kill "$BACKEND_PID" 2>/dev/null || true
|
||
exit 1
|
||
fi
|
||
|
||
# =============================================================================
|
||
# 3. 启动隧道服务
|
||
# =============================================================================
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动隧道服务..."
|
||
|
||
# 检查隧道环境变量
|
||
if [ -z "$SERVER_ADDRS" ] || [ -z "$SERVICE_ID" ] || [ -z "$LOCAL_PORT" ]; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:隧道环境变量缺失,隧道将不会启动"
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 需要 SERVER_ADDRS, SERVICE_ID, LOCAL_PORT"
|
||
TUNNEL_PID=""
|
||
else
|
||
# 启动隧道(保留错误日志用于诊断)
|
||
/usr/local/bin/portwardenc >/tmp/tunnel.log 2>&1 &
|
||
TUNNEL_PID=$!
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 隧道PID: $TUNNEL_PID (日志: /tmp/tunnel.log)"
|
||
|
||
# 保存 PID 到文件
|
||
echo "$TUNNEL_PID" > /tmp/tunnel.pid 2>/dev/null || true
|
||
|
||
# 等待隧道启动
|
||
sleep 2
|
||
|
||
# 检查隧道是否启动成功
|
||
if ! kill -0 "$TUNNEL_PID" 2>/dev/null; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:隧道启动失败或已退出"
|
||
TUNNEL_PID=""
|
||
fi
|
||
fi
|
||
|
||
# =============================================================================
|
||
# 4. 监控服务状态
|
||
# =============================================================================
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ============================================"
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 所有服务启动成功!"
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] - 前端: http://localhost:3001 (通过隧道暴露)"
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] - 后端: http://localhost:8000 (仅容器内部)"
|
||
if [ -n "$TUNNEL_PID" ]; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] - 隧道: PID $TUNNEL_PID (自动重启已启用)"
|
||
else
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] - 隧道: 未运行 (请检查环境变量)"
|
||
fi
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ============================================"
|
||
|
||
# 持续监控进程状态
|
||
while true; do
|
||
# 检查后端
|
||
if ! kill -0 "$BACKEND_PID" 2>/dev/null; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:后端进程已停止!"
|
||
kill "$FRONTEND_PID" 2>/dev/null || true
|
||
if [ -n "$TUNNEL_PID" ]; then
|
||
kill "$TUNNEL_PID" 2>/dev/null || true
|
||
fi
|
||
exit 1
|
||
fi
|
||
|
||
# 检查前端
|
||
if ! kill -0 "$FRONTEND_PID" 2>/dev/null; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:前端进程已停止!"
|
||
kill "$BACKEND_PID" 2>/dev/null || true
|
||
if [ -n "$TUNNEL_PID" ]; then
|
||
kill "$TUNNEL_PID" 2>/dev/null || true
|
||
fi
|
||
exit 1
|
||
fi
|
||
|
||
# 检查隧道(如果已启用)
|
||
if [ -n "$TUNNEL_PID" ]; then
|
||
if ! kill -0 "$TUNNEL_PID" 2>/dev/null; then
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:隧道进程已停止,尝试自动重启..."
|
||
restart_tunnel
|
||
fi
|
||
fi
|
||
|
||
sleep 5
|
||
done
|