243 lines
6.5 KiB
Bash
243 lines
6.5 KiB
Bash
|
|
#!/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
|
|||
|
|
|