#!/bin/bash # Sage Web Application Start Script # 多进程支持: 端口复用 + 独立后台程序 # # 架构说明: # 1. 独立后台程序 (bin/*.py) - 每个只启动一次,避免重复 # 2. Sage Web Workers - 根据CPU核心数启动多个worker,使用端口复用 set -e # 切换到脚本所在目录 cd "$(dirname "$0")" # 配置 WORKDIR="$(pwd)" PYTHON="./py3/bin/python" APP_ENTRY="app/sage.py" PIDFILE="$WORKDIR/sage.pid" LOGDIR="$WORKDIR/logs" BINPIDFILE="$WORKDIR/sage_backend.pid" # 确保logs目录存在 mkdir -p "$LOGDIR" # 检查Python是否存在 if [ ! -f "$PYTHON" ]; then echo "错误: 找不到Python解释器 $PYTHON" echo "请确保已安装虚拟环境: ./py3/bin/python" exit 1 fi # 检查应用入口文件是否存在 if [ ! -f "$APP_ENTRY" ]; then echo "错误: 找不到应用入口文件 $APP_ENTRY" exit 1 fi # 检查Redis是否运行(session存储依赖) if command -v redis-cli &> /dev/null; then if ! redis-cli ping &> /dev/null; then echo "Redis未运行,正在启动Redis..." redis-server --daemonize yes sleep 1 if redis-cli ping &> /dev/null; then echo "Redis启动成功" else echo "警告: Redis启动失败,登录功能可能无法正常工作" fi else echo "Redis运行正常" fi fi echo "=========================================" echo "启动 Sage Web Application" echo "工作目录: $WORKDIR" echo "Python: $PYTHON" echo "=========================================" # 获取端口 PORT=9180 if command -v python3 &> /dev/null; then PORT=$($PYTHON -c " import json try: with open('$WORKDIR/conf/config.json') as f: config = json.load(f) print(config.get('website', {}).get('port', 9180)) except Exception as e: print(9180) " 2>/dev/null || echo 9180) fi # ========================================= # 步骤 1: 启动独立后台程序 # ========================================= echo "" echo "--- 启动独立后台程序 ---" # 清空后台程序 PID 文件 > "$BINPIDFILE" # 1.1 启动 LLM 后台计费程序 if [ -f "$WORKDIR/bin/backend_accounting.py" ]; then LOGFILE="$LOGDIR/backend_accounting.log" echo ">>> 启动 backend_accounting ..." nohup $PYTHON "$WORKDIR/bin/backend_accounting.py" > "$LOGFILE" 2>&1 & PID=$! echo "backend_accounting:$PID" >> "$BINPIDFILE" sleep 0.5 if kill -0 $PID 2>/dev/null; then echo " -> backend_accounting PID: $PID (成功)" else echo " -> 警告: backend_accounting 启动失败,查看 $LOGFILE" fi fi # ========================================= # 步骤 2: 启动 Sage Web Workers (端口复用) # ========================================= echo "" echo "--- 启动 Sage Web Workers (端口复用) ---" # 获取 CPU 核心数,决定启动多少 Worker WORKERS=$(nproc) echo "检测到 ${WORKERS} 个 CPU 核心,准备启动 ${WORKERS} 个 worker 进程..." echo "所有 worker 共享端口 ${PORT} (SO_REUSEPORT)" # 清空 Worker PID 文件 > "$PIDFILE" # 循环启动 Worker for (( i=0; i>> 启动 Worker $((i+1))/${WORKERS} on port $PORT ..." # 启动服务 - 所有worker使用相同端口,依赖ahserver的SO_REUSEPORT支持 nohup $PYTHON $APP_ENTRY --workdir "$WORKDIR" --port $PORT > "$LOGFILE" 2>&1 & APP_PID=$! # 保存 PID echo "$APP_PID" >> "$PIDFILE" # 短暂等待以检查是否立即崩溃 sleep 1 if kill -0 $APP_PID 2>/dev/null; then echo " -> Worker PID: $APP_PID (成功)" else echo " -> 错误: Worker 启动失败,请查看 $LOGFILE" fi done echo "" echo "=========================================" echo "所有服务已启动" echo "Worker PID 文件: $PIDFILE" echo "Backend PID 文件: $BINPIDFILE" echo "访问地址: http://localhost:${PORT}" echo "========================================="