#!/bin/bash # 配置参数 PYTHON_ENV="/home/work/keyword_crawl/venv" # Python虚拟环境 APP_DIR="/home/work/ai_wht" # 应用代码目录 APP_FILE="$APP_DIR/flask_wht_server_api.py" # 应用文件 APP_NAME="flask_wht_server_api:app" # Gunicorn应用名称 PORT="8216" WORKERS="6" LOG_FILE="$APP_DIR/log10bjh_wht_server_api_$(date +%y%m%d%H%M).log" PID_FILE="/tmp/gunicorn_wht_server_api.pid" TIMEOUT=120 echo "==========================================" echo "启动 Flask 应用服务器" echo "==========================================" echo "Python环境: $PYTHON_ENV" echo "应用目录: $APP_DIR" echo "应用文件: $(basename $APP_FILE)" echo "端口: $PORT" echo "工作进程: $WORKERS" echo "日志文件: $LOG_FILE" echo "==========================================" # 检查应用文件是否存在 if [ ! -f "$APP_FILE" ]; then echo "❌ 错误: 找不到应用文件 $APP_FILE" exit 1 fi # 检查虚拟环境 if [ ! -f "$PYTHON_ENV/bin/activate" ]; then echo "❌ 错误: 找不到虚拟环境 $PYTHON_ENV" exit 1 fi # 切换到应用目录 cd "$APP_DIR" || { echo "❌ 错误: 无法进入应用目录 $APP_DIR" exit 1 } echo "当前工作目录: $(pwd)" echo "目录内容:" ls -la *.py # 激活虚拟环境 echo "" echo "激活虚拟环境..." source "$PYTHON_ENV/bin/activate" echo "Python路径: $(which python)" echo "Python版本: $(python --version 2>&1)" # 检查gunicorn if ! command -v gunicorn &> /dev/null; then echo "❌ 错误: gunicorn 未安装" echo "请执行: pip install gunicorn" exit 1 fi echo "Gunicorn路径: $(which gunicorn)" echo "Gunicorn版本: $(gunicorn --version 2>&1)" # 添加应用目录到Python路径 export PYTHONPATH="$APP_DIR:$PYTHONPATH" echo "PYTHONPATH: $PYTHONPATH" # 测试导入 echo "" echo "测试应用导入..." python -c " import sys print('Python路径:') for p in sys.path[:5]: print(f' {p}') print('...') try: # 尝试导入 import importlib.util import os module_name = 'flask_wht_server_api' file_path = '$APP_FILE' spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) print('✅ 成功加载模块') # 检查是否有app对象 if hasattr(module, 'app'): print('✅ 找到 Flask app 对象') app = module.app print(f' App名称: {app.name if hasattr(app, "name") else "未知"}') else: # 检查其他可能的名称 for attr_name in ['application', 'flask_app', 'create_app']: if hasattr(module, attr_name): print(f'✅ 找到 {attr_name} 对象') break else: print('⚠️ 未找到标准的Flask应用对象') print('可用的属性:', [a for a in dir(module) if not a.startswith('_')][:10]) except Exception as e: print(f'❌ 导入失败: {e}') import traceback traceback.print_exc() " # (1) 停止现有进程 echo "" echo "停止现有进程..." # 通过PID文件停止 if [ -f "$PID_FILE" ]; then OLD_PID=$(cat "$PID_FILE" 2>/dev/null) if [ -n "$OLD_PID" ] && kill -0 "$OLD_PID" 2>/dev/null; then echo "停止进程 $OLD_PID..." kill "$OLD_PID" sleep 3 if kill -0 "$OLD_PID" 2>/dev/null; then echo "强制停止进程 $OLD_PID..." kill -9 "$OLD_PID" fi fi rm -f "$PID_FILE" fi # 通过进程名停止 echo "查找相关进程..." PIDS=$(ps aux | grep -E "(gunicorn.*flask_wht_server_api|python.*flask_wht_server_api)" | grep -v grep | awk '{print $2}') if [ -n "$PIDS" ]; then echo "停止进程: $PIDS" for PID in $PIDS; do kill "$PID" 2>/dev/null sleep 1 if kill -0 "$PID" 2>/dev/null; then kill -9 "$PID" 2>/dev/null fi done fi sleep 2 # 检查端口占用 if lsof -ti:$PORT >/dev/null 2>&1; then echo "⚠️ 端口 $PORT 仍被占用,强制清理..." lsof -ti:$PORT | xargs kill -9 2>/dev/null sleep 2 fi # (2) 启动新进程 echo "" echo "启动 Gunicorn 服务器..." # 构建启动命令 GUNICORN_CMD="gunicorn" CMD_ARGS="-w $WORKERS -b 0.0.0.0:$PORT --pid $PID_FILE --timeout $TIMEOUT --access-logfile $APP_DIR/access.log --error-logfile $APP_DIR/error.log --log-level info --preload '$APP_NAME'" echo "执行命令:" echo "$GUNICORN_CMD $CMD_ARGS" # 启动服务(后台运行) nohup $GUNICORN_CMD -w $WORKERS \ -b 0.0.0.0:$PORT \ --pid $PID_FILE \ --timeout $TIMEOUT \ --access-logfile "$APP_DIR/access.log" \ --error-logfile "$APP_DIR/error.log" \ --log-level info \ --preload \ "$APP_NAME" >> "$LOG_FILE" 2>&1 & # 等待启动 echo -n "等待服务启动" for i in {1..20}; do if [ -f "$PID_FILE" ] && [ -s "$PID_FILE" ]; then SERVER_PID=$(cat "$PID_FILE") if kill -0 "$SERVER_PID" 2>/dev/null; then echo "" echo "✅ 服务已启动,PID: $SERVER_PID" break fi fi echo -n "." sleep 1 done echo "" # 检查状态 if [ -f "$PID_FILE" ]; then SERVER_PID=$(cat "$PID_FILE") echo "" echo "服务器状态:" echo "PID文件: $PID_FILE" echo "主进程PID: $SERVER_PID" # 检查进程 if ps -p "$SERVER_PID" > /dev/null; then echo "进程状态: ✅ 运行中" # 检查端口 sleep 2 if netstat -tulpn 2>/dev/null | grep ":$PORT " >/dev/null; then echo "端口状态: ✅ $PORT 监听中" else echo "端口状态: ⚠️ $PORT 未监听" fi # 检查worker进程 WORKER_COUNT=$(ps -ef | grep "gunicorn.*worker" | grep -v grep | wc -l) echo "工作进程: $WORKER_COUNT" echo "" echo "✅ 部署成功!" echo "访问地址: http://localhost:$PORT" echo "日志文件: $LOG_FILE" echo "错误日志: $APP_DIR/error.log" echo "访问日志: $APP_DIR/access.log" else echo "❌ 进程未运行" echo "请查看日志文件: $LOG_FILE" echo "最后10行日志:" tail -10 "$LOG_FILE" 2>/dev/null || echo "无法读取日志文件" fi else echo "❌ PID文件未创建,启动失败" echo "请查看日志文件: $LOG_FILE" echo "最后10行日志:" tail -10 "$LOG_FILE" 2>/dev/null || echo "无法读取日志文件" fi