#!/usr/bin/env bash # xiaoqu-agent-service 本机部署脚本(dev:本机开发 + 本机运行) # 用法: ./deploy/deploy.sh {build|start|stop|restart|status|log} # 凭据: 首次使用复制 deploy/.env.example 为 deploy/.env.dev 并填写(该文件已 gitignore,不入库) set -euo pipefail APP_HOME="$(cd "$(dirname "$0")/.." && pwd)" JAR="$APP_HOME/target/xiaoqu-agent-service.jar" ENV_FILE="$APP_HOME/deploy/.env.dev" PID_FILE="$APP_HOME/deploy/app.pid" LOG_DIR="$APP_HOME/logs" LOG_FILE="$LOG_DIR/agent-service.log" PORT=8088 PROFILE=dev load_env() { if [ ! -f "$ENV_FILE" ]; then echo "[ERROR] 缺少 $ENV_FILE,请复制 deploy/.env.example 并填写 dev 凭据" >&2 exit 1 fi set -a; source "$ENV_FILE"; set +a } is_running() { [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null } health_check() { # /mcp 未带 ak 会返回 401,带 ak 返回 200——两者都证明服务已起来 for i in $(seq 1 90); do if ! is_running; then echo "[ERROR] 服务进程已退出,可能是数据库迁移或启动失败" >&2 tail -40 "$LOG_FILE" >&2 || true rm -f "$PID_FILE" return 1 fi code=$(curl -s -o /dev/null -w "%{http_code}" -X POST "http://127.0.0.1:$PORT/mcp" \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"deploy-check","version":"0"}}}' || true) if [ "$code" = "200" ] || [ "$code" = "401" ]; then echo "[OK] 服务已就绪 (HTTP $code, /mcp)" return 0 fi sleep 2 done echo "[ERROR] 健康检查超时,查看日志: tail -f $LOG_FILE" >&2 return 1 } do_build() { cd "$APP_HOME" ./mvnw clean package echo "[OK] 构建完成: $JAR" } do_start() { if is_running; then echo "[SKIP] 已在运行 (pid $(cat "$PID_FILE"))" return 0 fi [ -f "$JAR" ] || { echo "[ERROR] 未找到 jar,先执行: $0 build" >&2; exit 1; } load_env mkdir -p "$LOG_DIR" cd "$APP_HOME" nohup java -jar "$JAR" --spring.profiles.active="$PROFILE" >> "$LOG_FILE" 2>&1 & echo $! > "$PID_FILE" echo "[OK] 已启动 (pid $(cat "$PID_FILE")),等待健康检查..." health_check } do_stop() { if is_running; then kill "$(cat "$PID_FILE")" for i in $(seq 1 15); do is_running || break; sleep 1; done is_running && { echo "[WARN] 优雅退出超时,强制 kill -9"; kill -9 "$(cat "$PID_FILE")"; } echo "[OK] 已停止" else echo "[SKIP] 未在运行" fi rm -f "$PID_FILE" } do_status() { if is_running; then echo "运行中 (pid $(cat "$PID_FILE"), port $PORT)" else echo "未运行" exit 1 fi } case "${1:-}" in build) do_build ;; start) do_start ;; stop) do_stop ;; restart) do_stop; do_start ;; status) do_status ;; log) tail -f "$LOG_FILE" ;; *) echo "用法: $0 {build|start|stop|restart|status|log}" >&2 exit 1 ;; esac