Files
ai_baijiahao/start.sh

357 lines
12 KiB
Bash
Raw Permalink 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
###############################################################################
# 百家号爬虫系统 - 快速启动脚本
# 功能:杀死旧进程 -> 激活虚拟环境 -> 启动服务 -> 检查状态
# 支持nohup / gunicorn 两种启动方式
# 新增TaskWorker 监控和健康检查
###############################################################################
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# 项目配置
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
VENV_DIR="${PROJECT_DIR}/venv"
APP_PORT=8030
PID_FILE="${PROJECT_DIR}/app.pid"
GUNICORN_PID_FILE="${PROJECT_DIR}/gunicorn.pid"
MONITOR_PID_FILE="${PROJECT_DIR}/monitor.pid"
# 启动模式(默认使用 gunicorn
START_MODE="${1:-gunicorn}" # gunicorn 或 nohup
ENABLE_MONITOR="${2:-yes}" # 是否启动监控yes/no
echo -e "${BLUE}=========================================${NC}"
echo -e "${BLUE} 百家号爬虫系统 - 启动服务${NC}"
echo -e "${BLUE} 启动模式: ${START_MODE}${NC}"
echo -e "${BLUE} 自动监控: ${ENABLE_MONITOR}${NC}"
echo -e "${BLUE}=========================================${NC}"
echo ""
###############################################################################
# 1. 杀死旧进程
###############################################################################
echo -e "${YELLOW}[1/3]${NC} 检查并停止旧服务..."
# 通过 PID 文件停止
if [[ -f "${PID_FILE}" ]]; then
OLD_PID=$(cat ${PID_FILE})
if ps -p ${OLD_PID} > /dev/null 2>&1; then
echo " 发现旧进程 (PID: ${OLD_PID}),正在停止..."
kill ${OLD_PID} 2>/dev/null
sleep 2
# 如果还在运行,强制终止
if ps -p ${OLD_PID} > /dev/null 2>&1; then
echo " 强制终止进程..."
kill -9 ${OLD_PID} 2>/dev/null
fi
echo -e " ${GREEN}${NC} 旧进程已停止"
fi
rm -f ${PID_FILE}
fi
# 停止 Gunicorn
if [[ -f "${GUNICORN_PID_FILE}" ]]; then
GUNICORN_PID=$(cat ${GUNICORN_PID_FILE})
if ps -p ${GUNICORN_PID} > /dev/null 2>&1; then
echo " 发现 Gunicorn 进程 (PID: ${GUNICORN_PID}),正在停止..."
kill ${GUNICORN_PID} 2>/dev/null
sleep 2
if ps -p ${GUNICORN_PID} > /dev/null 2>&1; then
echo " 强制终止 Gunicorn..."
kill -9 ${GUNICORN_PID} 2>/dev/null
fi
echo -e " ${GREEN}${NC} Gunicorn 进程已停止"
fi
rm -f ${GUNICORN_PID_FILE}
fi
# 杀死所有 app.py 相关进程(包括任务线程)
APP_PIDS=$(ps aux | grep "[p]ython.*app.py" | awk '{print $2}')
if [[ -n "${APP_PIDS}" ]]; then
echo " 发现运行中的 Python 进程,正在清理..."
for pid in ${APP_PIDS}; do
echo " 停止进程 ${pid}..."
kill ${pid} 2>/dev/null
done
sleep 2
# 强制清理残留进程
APP_PIDS=$(ps aux | grep "[p]ython.*app.py" | awk '{print $2}')
if [[ -n "${APP_PIDS}" ]]; then
echo " 强制清理残留进程..."
for pid in ${APP_PIDS}; do
kill -9 ${pid} 2>/dev/null
done
fi
echo -e " ${GREEN}${NC} 所有旧进程已清理"
else
echo -e " ${GREEN}${NC} 未发现运行中的进程"
fi
# 清理端口占用
PORT_PID=$(lsof -ti:${APP_PORT} 2>/dev/null)
if [[ -n "${PORT_PID}" ]]; then
echo " 端口 ${APP_PORT} 被占用 (PID: ${PORT_PID}),正在释放..."
kill -9 ${PORT_PID} 2>/dev/null
echo -e " ${GREEN}${NC} 端口已释放"
fi
# 停止监控进程
if [[ -f "${MONITOR_PID_FILE}" ]]; then
MONITOR_PID=$(cat ${MONITOR_PID_FILE})
if ps -p ${MONITOR_PID} > /dev/null 2>&1; then
echo " 发现监控进程 (PID: ${MONITOR_PID}),正在停止..."
kill ${MONITOR_PID} 2>/dev/null
sleep 1
echo -e " ${GREEN}${NC} 监控进程已停止"
fi
rm -f ${MONITOR_PID_FILE}
fi
# 清理 TaskWorker 锁文件
if [[ -f "data/taskworker.lock" ]]; then
echo " 清理 TaskWorker 锁文件..."
rm -f data/taskworker.lock
echo -e " ${GREEN}${NC} 锁文件已清理"
fi
echo ""
###############################################################################
# 2. 激活虚拟环境
###############################################################################
echo -e "${YELLOW}[2/3]${NC} 激活虚拟环境..."
if [[ ! -d "${VENV_DIR}" ]]; then
echo -e " ${RED}${NC} 虚拟环境不存在: ${VENV_DIR}"
echo " 请先创建虚拟环境:"
echo " python3 -m venv .venv"
echo " source .venv/bin/activate"
echo " pip install -r requirements.txt"
exit 1
fi
source ${VENV_DIR}/bin/activate
if [[ "$VIRTUAL_ENV" != "" ]]; then
echo -e " ${GREEN}${NC} 虚拟环境已激活: ${VIRTUAL_ENV}"
else
echo -e " ${RED}${NC} 虚拟环境激活失败"
exit 1
fi
echo ""
###############################################################################
# 3. 启动服务
###############################################################################
echo -e "${YELLOW}[3/5]${NC} 启动服务..."
cd ${PROJECT_DIR}
if [[ "${START_MODE}" == "gunicorn" ]]; then
# 使用 Gunicorn 启动
echo " 使用 Gunicorn 启动服务..."
# 检查 gunicorn 是否安装
if ! command -v gunicorn &> /dev/null; then
echo -e " ${RED}${NC} Gunicorn 未安装,请先安装:"
echo " pip install gunicorn"
exit 1
fi
# 后台启动 Gunicorn
gunicorn -c gunicorn_config.py app:app
# 等待服务启动daemon模式需要更长时间
echo " 等待服务启动..."
sleep 5
# 检查服务是否成功启动
if [[ -f "${GUNICORN_PID_FILE}" ]]; then
GUNICORN_PID=$(cat ${GUNICORN_PID_FILE})
if ps -p ${GUNICORN_PID} > /dev/null 2>&1; then
echo ""
echo -e "${GREEN}=========================================${NC}"
echo -e "${GREEN} Gunicorn 服务启动成功!${NC}"
echo -e "${GREEN}=========================================${NC}"
echo ""
echo -e " PID: ${GUNICORN_PID}"
echo -e " 端口: ${APP_PORT}"
echo -e " 访问地址: http://0.0.0.0:${APP_PORT}"
echo -e " 访问日志: logs/gunicorn_access.log"
echo -e " 错误日志: logs/gunicorn_error.log"
echo ""
echo -e "查看日志: ${BLUE}tail -f logs/gunicorn_error.log${NC}"
echo -e "停止服务: ${BLUE}./stop.sh${NC}"
echo -e "重启服务: ${BLUE}./restart.sh${NC}"
echo -e "检查状态: ${BLUE}python check_taskworker.py${NC}"
echo ""
else
echo ""
echo -e "${RED}=========================================${NC}"
echo -e "${RED} Gunicorn 启动失败!${NC}"
echo -e "${RED}=========================================${NC}"
echo ""
echo "请检查日志文件:"
echo " tail -n 50 logs/gunicorn_error.log"
echo ""
exit 1
fi
else
# 尝试通过端口检查服务是否启动
echo " PID文件未生成检查端口占用..."
sleep 2
if lsof -i:${APP_PORT} > /dev/null 2>&1; then
echo ""
echo -e "${GREEN}=========================================${NC}"
echo -e "${GREEN} Gunicorn 服务已启动!${NC}"
echo -e "${GREEN}=========================================${NC}"
echo ""
echo -e " 端口: ${APP_PORT}"
echo -e " 访问地址: http://0.0.0.0:${APP_PORT}"
echo -e " 访问日志: logs/gunicorn_access.log"
echo -e " 错误日志: logs/gunicorn_error.log"
echo ""
echo -e "查看日志: ${BLUE}tail -f logs/gunicorn_error.log${NC}"
echo -e "停止服务: ${BLUE}./stop.sh${NC}"
echo -e "检查状态: ${BLUE}python check_taskworker.py${NC}"
echo ""
else
echo -e "${RED}${NC} 服务启动失败,请检查错误日志:"
echo " tail -n 50 logs/gunicorn_error.log"
exit 1
fi
fi
else
# 使用 nohup 启动
echo " 使用 nohup 启动服务..."
# 后台启动
nohup python app.py > logs/app.log 2>&1 &
NEW_PID=$!
# 保存 PID
echo ${NEW_PID} > ${PID_FILE}
# 等待服务启动
echo " 等待服务启动..."
sleep 3
# 检查服务是否成功启动
if ps -p ${NEW_PID} > /dev/null 2>&1; then
echo ""
echo -e "${GREEN}=========================================${NC}"
echo -e "${GREEN} 服务启动成功!${NC}"
echo -e "${GREEN}=========================================${NC}"
echo ""
echo -e " PID: ${NEW_PID}"
echo -e " 端口: ${APP_PORT}"
echo -e " 访问地址: http://127.0.0.1:${APP_PORT}"
echo -e " 日志文件: logs/app.log"
echo ""
echo -e "查看日志: ${BLUE}tail -f logs/app.log${NC}"
echo -e "停止服务: ${BLUE}kill ${NEW_PID}${NC}"
echo -e "检查状态: ${BLUE}python check_taskworker.py${NC}"
echo ""
else
echo ""
echo -e "${RED}=========================================${NC}"
echo -e "${RED} 服务启动失败!${NC}"
echo -e "${RED}=========================================${NC}"
echo ""
echo "请检查日志文件:"
echo " tail -n 50 logs/app.log"
echo ""
exit 1
fi
fi
echo ""
###############################################################################
# 4. 检查 TaskWorker 状态
###############################################################################
echo -e "${YELLOW}[4/5]${NC} 检查 TaskWorker 状态..."
# 等待服务完全启动
sleep 3
# 检查健康状态
if command -v curl &> /dev/null; then
HEALTH_CHECK=$(curl -s http://localhost:${APP_PORT}/health/taskworker 2>/dev/null)
if [[ -n "${HEALTH_CHECK}" ]]; then
STATUS=$(echo ${HEALTH_CHECK} | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
if [[ "${STATUS}" == "healthy" ]]; then
echo -e " ${GREEN}${NC} TaskWorker 状态: ${GREEN}healthy${NC}"
# 提取详细信息
ALIVE_THREADS=$(echo ${HEALTH_CHECK} | grep -o '"alive_threads":[0-9]*' | cut -d':' -f2)
PENDING=$(echo ${HEALTH_CHECK} | grep -o '"pending":[0-9]*' | cut -d':' -f2)
echo " 活跃线程: ${ALIVE_THREADS}"
echo " 待处理任务: ${PENDING}"
else
echo -e " ${YELLOW}${NC} TaskWorker 状态: ${YELLOW}${STATUS}${NC}"
echo " 建议运行: python check_taskworker.py --fix"
fi
else
echo -e " ${YELLOW}${NC} 无法连接到服务,稍后重试"
fi
else
echo " 跳过健康检查curl 未安装)"
fi
echo ""
###############################################################################
# 5. 启动监控进程(可选)
###############################################################################
if [[ "${ENABLE_MONITOR}" == "yes" ]]; then
echo -e "${YELLOW}[5/5]${NC} 启动 TaskWorker 自动监控..."
if [[ -f "taskworker_monitor.py" ]]; then
# 后台启动监控
nohup python taskworker_monitor.py > logs/monitor.out 2>&1 &
MONITOR_PID=$!
echo ${MONITOR_PID} > ${MONITOR_PID_FILE}
sleep 1
if ps -p ${MONITOR_PID} > /dev/null 2>&1; then
echo -e " ${GREEN}${NC} 监控进程已启动 (PID: ${MONITOR_PID})"
echo " 监控日志: logs/taskworker_monitor.log"
echo " 输出日志: logs/monitor.out"
else
echo -e " ${YELLOW}${NC} 监控进程启动失败"
fi
else
echo -e " ${YELLOW}${NC} 监控脚本不存在: taskworker_monitor.py"
fi
else
echo -e "${YELLOW}[5/5]${NC} 跳过自动监控(使用 './start.sh gunicorn yes' 启用)"
fi
echo ""
echo -e "${GREEN}=========================================${NC}"
echo -e "${GREEN} 服务启动完成!${NC}"
echo -e "${GREEN}=========================================${NC}"
echo ""