#!/bin/bash # Agent 服务管理脚本 # 服务配置 SERVICE_NAME="knowledge-agent" PID_FILE="/tmp/${SERVICE_NAME}.pid" LOG_FILE="logs/agent.log" PORT=8080 # 创建日志目录 mkdir -p logs # 显示帮助信息 show_help() { echo "Usage: $0 {start|stop|restart|status|logs}" echo "" echo "Commands:" echo " start - 启动服务" echo " stop - 停止服务" echo " restart - 重启服务" echo " status - 查看服务状态" echo " logs - 查看实时日志" echo "" echo "Examples:" echo " $0 start # 启动服务" echo " $0 stop # 停止服务" echo " $0 logs # 查看实时日志" echo " tail -f logs/agent.log # 也可以直接使用 tail 命令" } # 检查服务是否运行 is_running() { if [ -f "$PID_FILE" ]; then pid=$(cat "$PID_FILE") if ps -p "$pid" > /dev/null 2>&1; then return 0 else rm -f "$PID_FILE" fi fi return 1 } # 启动服务 start_service() { echo "🚀 启动 ${SERVICE_NAME} 服务..." # 检查Python环境 if ! command -v python3 &> /dev/null; then echo "❌ 错误: 未找到 python3 命令" exit 1 fi # 检查依赖 echo "📦 检查依赖..." python3 -c "import fastapi, uvicorn" 2>/dev/null if [ $? -ne 0 ]; then echo "❌ 错误: 缺少必要的依赖包" echo "请运行: pip install -r requirements.txt" exit 1 fi # 检查 httpx echo "🔍 检查 httpx..." python3 -c "import httpx" 2>/dev/null if [ $? -ne 0 ]; then echo "❌ 错误: 缺少 httpx 依赖包" echo "请运行: pip install httpx" exit 1 fi # 检查 LangGraph echo "🔍 检查 LangGraph..." python3 -c "import langgraph" 2>/dev/null if [ $? -ne 0 ]; then echo "⚠️ 警告: LangGraph 未安装,将使用传统模式" echo "如需启用 LangGraph,请运行: pip install langgraph" echo "" fi # 检查服务是否已经运行 if is_running; then echo "⚠️ 警告: 服务已经在运行中 (PID: $(cat "$PID_FILE"))" echo "如需重启,请使用: $0 restart" exit 1 fi # 启动服务 echo "🌟 启动服务..." echo "📍 服务地址: http://localhost:${PORT}" echo "📚 API文档: http://localhost:${PORT}/docs" echo "🔍 健康检查: http://localhost:${PORT}/health" echo "📝 日志文件: ${LOG_FILE}" echo "" # 后台启动服务,记录PID # 生产环境禁用热重载以减少日志噪音 export RELOAD_ENABLED=false export LOG_LEVEL=info export LANGCHAIN_TRACING_V2=true export LANGCHAIN_API_KEY=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 export LANGCHAIN_PROJECT=knowledge-agent nohup python3 agent.py > "$LOG_FILE" 2>&1 & echo $! > "$PID_FILE" # 等待服务启动 sleep 2 if is_running; then echo "✅ 服务启动成功! (PID: $(cat "$PID_FILE"))" echo "📝 查看日志: $0 logs 或 tail -f ${LOG_FILE}" echo "🛑 停止服务: $0 stop" else echo "❌ 服务启动失败,请检查日志: ${LOG_FILE}" rm -f "$PID_FILE" exit 1 fi } # 停止服务 stop_service() { echo "🛑 停止 ${SERVICE_NAME} 服务..." if is_running; then pid=$(cat "$PID_FILE") echo "正在停止进程 PID: $pid" # 尝试优雅停止 kill "$pid" 2>/dev/null # 等待进程结束 for i in {1..15}; do if ! ps -p "$pid" > /dev/null 2>&1; then break fi echo "等待进程结束... ($i/15)" sleep 1 done # 如果进程仍然存在,强制杀死 if ps -p "$pid" > /dev/null 2>&1; then echo "强制停止进程..." kill -9 "$pid" 2>/dev/null fi rm -f "$PID_FILE" echo "✅ 主进程已停止" else echo "ℹ️ 主进程未运行" fi # 额外清理:查找并终止所有相关进程 echo "🔍 检查是否有残留进程..." # 查找所有可能的进程类型 REMAINING_PROCESSES=$(ps aux | grep -E "(python.*agent\.py|uvicorn.*agent|knowledge-agent|agent\.py|multiprocessing\.spawn|multiprocessing\.resource_tracker)" | grep -v grep | awk '{print $2}') if [ ! -z "$REMAINING_PROCESSES" ]; then echo "⚠️ 发现残留进程,正在清理..." echo "📋 找到的进程:" ps aux | grep -E "(python.*agent\.py|uvicorn.*agent|knowledge-agent|agent\.py|multiprocessing\.spawn|multiprocessing\.resource_tracker)" | grep -v grep # 先尝试优雅终止 for pid in $REMAINING_PROCESSES; do echo "优雅终止进程 $pid..." kill -TERM $pid 2>/dev/null done # 等待3秒 sleep 3 # 检查是否还有残留 STILL_REMAINING=$(ps aux | grep -E "(python.*agent\.py|uvicorn.*agent|knowledge-agent|agent\.py|multiprocessing\.spawn|multiprocessing\.resource_tracker)" | grep -v grep | awk '{print $2}') if [ ! -z "$STILL_REMAINING" ]; then echo "强制终止顽固进程..." for pid in $STILL_REMAINING; do echo "强制终止进程 $pid..." kill -9 $pid 2>/dev/null done # 再次等待并检查 sleep 2 FINAL_CHECK=$(ps aux | grep -E "(python.*agent\.py|uvicorn.*agent|knowledge-agent|agent\.py|multiprocessing\.spawn|multiprocessing\.resource_tracker)" | grep -v grep | awk '{print $2}') if [ ! -z "$FINAL_CHECK" ]; then echo "⚠️ 仍有进程无法终止,请手动检查:" ps aux | grep -E "(python.*agent\.py|uvicorn.*agent|knowledge-agent|agent\.py|multiprocessing\.spawn|multiprocessing\.resource_tracker)" | grep -v grep fi fi echo "✅ 残留进程已清理" else echo "✅ 没有发现残留进程" fi # 检查端口占用 echo "🔍 检查端口${PORT}占用情况..." PORT_PROCESS=$(lsof -ti:${PORT} 2>/dev/null) if [ ! -z "$PORT_PROCESS" ]; then echo "⚠️ 端口${PORT}仍被占用,进程ID: $PORT_PROCESS" echo "强制终止占用端口的进程..." kill -9 $PORT_PROCESS 2>/dev/null echo "✅ 端口已释放" else echo "✅ 端口${PORT}已释放" fi } # 重启服务 restart_service() { echo "🔄 重启 ${SERVICE_NAME} 服务..." stop_service sleep 2 start_service } # 查看服务状态 show_status() { echo "🔍 ${SERVICE_NAME} 服务状态:" if is_running; then pid=$(cat "$PID_FILE") echo "✅ 状态: 运行中" echo "📊 PID: $pid" echo "📍 端口: $PORT" echo "📝 日志: $LOG_FILE" echo "🔗 地址: http://localhost:${PORT}" # 显示进程信息 echo "" echo "📋 进程信息:" ps -p "$pid" -o pid,ppid,cmd,etime else echo "❌ 状态: 未运行" echo "💡 启动服务: $0 start" fi } # 查看实时日志 show_logs() { echo "📝 查看实时日志 (按 Ctrl+C 退出)..." echo "日志文件: ${LOG_FILE}" echo "" if [ -f "$LOG_FILE" ]; then tail -f "$LOG_FILE" else echo "❌ 日志文件不存在: ${LOG_FILE}" echo "请先启动服务: $0 start" exit 1 fi } # 主逻辑 case "$1" in start) start_service ;; stop) stop_service ;; restart) restart_service ;; status) show_status ;; logs) show_logs ;; *) show_help exit 1 ;; esac