#!/usr/bin/env bash # # ZeekerWatchman — 一键启动脚本 # 自动安装依赖、启动后端和前端服务 # set -e ROOT_DIR="$(cd "$(dirname "$0")" && pwd)" BACKEND_PORT=8765 FRONTEND_PORT=3000 RED='\033[0;31m' GREEN='\033[0;32m' BLUE='\033[0;34m' NC='\033[0m' cleanup() { echo -e "\n${BLUE}正在停止服务...${NC}" kill $BACKEND_PID 2>/dev/null || true kill $FRONTEND_PID 2>/dev/null || true echo -e "${GREEN}服务已停止${NC}" exit 0 } trap cleanup SIGINT SIGTERM echo -e "${BLUE}========================================${NC}" echo -e "${BLUE} ZeekerWatchman — 测试用例智能管理平台${NC}" echo -e "${BLUE}========================================${NC}" echo "" # ---- 检查环境 ---- echo -e "${BLUE}[1/5] 检查运行环境...${NC}" if ! command -v python3 &>/dev/null; then echo -e "${RED}错误: 未找到 python3${NC}" exit 1 fi echo -e " Python: $(python3 --version)" if ! command -v node &>/dev/null; then echo -e "${RED}错误: 未找到 node${NC}" exit 1 fi echo -e " Node: $(node --version)" echo -e " npm: $(npm --version)" # ---- 安装 Python 依赖 ---- echo -e "\n${BLUE}[2/5] 安装 Python 依赖...${NC}" cd "$ROOT_DIR" pip install -q -r server/requirements.txt 2>&1 | tail -1 || { echo -e "${RED}Python 依赖安装失败,请检查 server/requirements.txt${NC}" exit 1 } echo -e "${GREEN} Python 依赖就绪${NC}" # ---- 安装前端依赖 ---- echo -e "\n${BLUE}[3/5] 安装前端依赖...${NC}" cd "$ROOT_DIR/web" if [ ! -d "node_modules" ]; then npm install --silent 2>&1 | tail -1 fi echo -e "${GREEN} 前端依赖就绪${NC}" # ---- 检查端口 ---- echo -e "\n${BLUE}[4/5] 检查端口占用...${NC}" if lsof -i:$BACKEND_PORT &>/dev/null 2>&1; then echo -e " 端口 $BACKEND_PORT 被占用,尝试释放..." kill $(lsof -t -i:$BACKEND_PORT) 2>/dev/null || true sleep 1 fi if lsof -i:$FRONTEND_PORT &>/dev/null 2>&1; then echo -e " 端口 $FRONTEND_PORT 被占用,尝试释放..." kill $(lsof -t -i:$FRONTEND_PORT) 2>/dev/null || true sleep 1 fi echo -e "${GREEN} 端口可用${NC}" # ---- 启动服务 ---- echo -e "\n${BLUE}[5/5] 启动服务...${NC}" # 后端 cd "$ROOT_DIR" PYTHONPATH=. python -m uvicorn server.main:app \ --host 0.0.0.0 --port $BACKEND_PORT \ --log-level info \ > /tmp/testflow-backend.log 2>&1 & BACKEND_PID=$! echo -e " 后端 PID: $BACKEND_PID (端口 $BACKEND_PORT)" # 等待后端就绪 for i in $(seq 1 15); do if curl -s http://localhost:$BACKEND_PORT/api/health &>/dev/null; then echo -e " ${GREEN}后端就绪 ✓${NC}" break fi if [ $i -eq 15 ]; then echo -e " ${RED}后端启动超时,查看日志: tail /tmp/testflow-backend.log${NC}" cleanup exit 1 fi sleep 1 done # 前端 cd "$ROOT_DIR/web" npx next dev --port $FRONTEND_PORT --hostname 0.0.0.0 \ > /tmp/testflow-frontend.log 2>&1 & FRONTEND_PID=$! echo -e " 前端 PID: $FRONTEND_PID (端口 $FRONTEND_PORT)" # 等待前端就绪 for i in $(seq 1 20); do if curl -s -o /dev/null -w "%{http_code}" http://localhost:$FRONTEND_PORT 2>/dev/null | grep -q "200"; then echo -e " ${GREEN}前端就绪 ✓${NC}" break fi if [ $i -eq 20 ]; then echo -e " ${RED}前端启动超时,查看日志: tail /tmp/testflow-frontend.log${NC}" cleanup exit 1 fi sleep 2 done # ---- 完成 ---- echo "" echo -e "${GREEN}========================================${NC}" echo -e "${GREEN} ZeekerWatchman 启动完成!${NC}" echo -e "${GREEN}========================================${NC}" echo "" echo -e " 前端页面: ${BLUE}http://localhost:$FRONTEND_PORT${NC}" echo -e " 后端 API: ${BLUE}http://localhost:$BACKEND_PORT/api/health${NC}" echo -e " API 文档: ${BLUE}http://localhost:$BACKEND_PORT/docs${NC}" echo "" echo -e " 后端日志: tail -f /tmp/testflow-backend.log" echo -e " 前端日志: tail -f /tmp/testflow-frontend.log" echo "" echo -e " 按 ${RED}Ctrl+C${NC} 停止所有服务" echo "" # 保持前台运行 wait