FA3-Datafetch/docker-entrypoint.sh
xucheng 8c53b318da feat: 实现隧道进程自动重启功能,修复容器内进程管理架构
- 重构隧道进程管理:将隧道启动从 entrypoint.sh 移至 docker-entrypoint.sh
- 添加隧道自动重启机制:监控循环每5秒检查隧道进程状态,异常退出时自动重启
- 增强日志记录:隧道输出重定向至 /tmp/tunnel.log 便于问题排查
- 修复原始架构问题:解决 exec 替换进程导致后台隧道失去父进程监控的问题
- 优化清理逻辑:在信号处理和错误退出时正确清理隧道进程
2026-01-18 18:58:27 +08:00

181 lines
5.9 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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