feat: 实现隧道进程自动重启功能,修复容器内进程管理架构

- 重构隧道进程管理:将隧道启动从 entrypoint.sh 移至 docker-entrypoint.sh
- 添加隧道自动重启机制:监控循环每5秒检查隧道进程状态,异常退出时自动重启
- 增强日志记录:隧道输出重定向至 /tmp/tunnel.log 便于问题排查
- 修复原始架构问题:解决 exec 替换进程导致后台隧道失去父进程监控的问题
- 优化清理逻辑:在信号处理和错误退出时正确清理隧道进程
This commit is contained in:
xucheng 2026-01-18 18:58:27 +08:00
parent 43c21b7658
commit 8c53b318da
2 changed files with 79 additions and 5 deletions

81
docker-entrypoint.sh Normal file → Executable file
View File

@ -1,11 +1,35 @@
#!/bin/bash #!/bin/bash
# ============================================================================= # =============================================================================
# FA3 Datafetch 容器启动脚本 # FA3 Datafetch 容器启动脚本
# 功能:启动后端 (FastAPI) 和前端 (Next.js),处理进程管理 # 功能:启动后端 (FastAPI)、前端 (Next.js) 和隧道,处理进程管理
# ============================================================================= # =============================================================================
set -e 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() { cleanup() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 收到停止信号,正在关闭服务..." echo "[$(date '+%Y-%m-%d %H:%M:%S')] 收到停止信号,正在关闭服务..."
@ -15,8 +39,11 @@ cleanup() {
if [ -n "$FRONTEND_PID" ]; then if [ -n "$FRONTEND_PID" ]; then
kill "$FRONTEND_PID" 2>/dev/null || true kill "$FRONTEND_PID" 2>/dev/null || true
fi fi
if [ -n "$TUNNEL_PID" ]; then
kill "$TUNNEL_PID" 2>/dev/null || true
fi
# 等待进程结束 # 等待进程结束
wait $BACKEND_PID $FRONTEND_PID 2>/dev/null || true wait $BACKEND_PID $FRONTEND_PID $TUNNEL_PID 2>/dev/null || true
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 所有服务已停止" echo "[$(date '+%Y-%m-%d %H:%M:%S')] 所有服务已停止"
exit 0 exit 0
} }
@ -77,12 +104,46 @@ if ! kill -0 "$FRONTEND_PID" 2>/dev/null; then
fi fi
# ============================================================================= # =============================================================================
# 3. 监控服务状态 # 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')] 所有服务启动成功!" 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:3001 (通过隧道暴露)"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] - 后端: http://localhost:8000 (仅容器内部)" 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')] ============================================" echo "[$(date '+%Y-%m-%d %H:%M:%S')] ============================================"
# 持续监控进程状态 # 持续监控进程状态
@ -91,6 +152,9 @@ while true; do
if ! kill -0 "$BACKEND_PID" 2>/dev/null; then if ! kill -0 "$BACKEND_PID" 2>/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:后端进程已停止!" echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:后端进程已停止!"
kill "$FRONTEND_PID" 2>/dev/null || true kill "$FRONTEND_PID" 2>/dev/null || true
if [ -n "$TUNNEL_PID" ]; then
kill "$TUNNEL_PID" 2>/dev/null || true
fi
exit 1 exit 1
fi fi
@ -98,8 +162,19 @@ while true; do
if ! kill -0 "$FRONTEND_PID" 2>/dev/null; then if ! kill -0 "$FRONTEND_PID" 2>/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:前端进程已停止!" echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:前端进程已停止!"
kill "$BACKEND_PID" 2>/dev/null || true kill "$BACKEND_PID" 2>/dev/null || true
if [ -n "$TUNNEL_PID" ]; then
kill "$TUNNEL_PID" 2>/dev/null || true
fi
exit 1 exit 1
fi 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 sleep 5
done done

3
entrypoint.sh Normal file → Executable file
View File

@ -141,8 +141,7 @@ export SERVER_ADDRS="$PW_SERVER_ADDRS"
export SERVICE_ID="$PW_SERVICE_ID" export SERVICE_ID="$PW_SERVICE_ID"
export LOCAL_PORT="$PW_LOCAL_PORT" export LOCAL_PORT="$PW_LOCAL_PORT"
echo "Starting Portwarden client in the background..." # 注意:隧道进程现在由 docker-entrypoint.sh 管理,不再在这里启动
/usr/local/bin/portwardenc &
echo "Executing main container command: $@" echo "Executing main container command: $@"
exec "$@" exec "$@"