#!/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