Files
ai_baijiahao/start.sh

357 lines
12 KiB
Bash
Raw Normal View History

#!/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 ""