diff --git a/xiaoqu-agent-service/.gitignore b/xiaoqu-agent-service/.gitignore index 458d8f9..439421e 100644 --- a/xiaoqu-agent-service/.gitignore +++ b/xiaoqu-agent-service/.gitignore @@ -4,3 +4,8 @@ target/ *.iml .vscode/ .DS_Store + +# 本地部署凭据与运行态 +deploy/.env.dev +deploy/app.pid +logs/ diff --git a/xiaoqu-agent-service/README.md b/xiaoqu-agent-service/README.md index 345dac5..0efd93f 100644 --- a/xiaoqu-agent-service/README.md +++ b/xiaoqu-agent-service/README.md @@ -111,6 +111,18 @@ nohup java -jar target/xiaoqu-agent-service.jar > target/app.log 2>&1 & - 不提供默认 profile、数据库账号或密码;缺失配置时不得启动。 - dev 端口 **8088**,MCP 端点 `http://localhost:8088/mcp`。 +### 部署脚本(推荐,本机 dev 部署) + +```bash +cp deploy/.env.example deploy/.env.dev # 填写 dev 凭据(已 gitignore,不入库) +./deploy/deploy.sh build # 构建 jar +./deploy/deploy.sh restart # 停旧起新 + 健康检查(/mcp 返回 401/200 即就绪) +./deploy/deploy.sh status | log | stop # 状态 / 跟踪日志 / 停止 +``` + +- 凭据从 `deploy/.env.dev` 读取,无需手工 export;日志在 `logs/agent-service.log`,pid 在 `deploy/app.pid`。 +- 注意应用启动较慢(多数据源初始化,约 60-90s),脚本健康检查窗口已放宽到 180s。 + ## 测试 ak(仅 dev) 仓库不提供固定 ak。每位开发者在本地生成随机 ak,只把 SHA-256 写入 `agent_api_key`,再用 `token_scope` 关联需要的作用域;明文只保存在本地环境变量中,不提交版本库。仓库历史中曾出现的 dev ak 必须视为已泄露并在数据库中禁用。 diff --git a/xiaoqu-agent-service/deploy/.env.example b/xiaoqu-agent-service/deploy/.env.example new file mode 100644 index 0000000..bd6712a --- /dev/null +++ b/xiaoqu-agent-service/deploy/.env.example @@ -0,0 +1,11 @@ +# dev 环境凭据(本文件为模板;实际使用复制为 .env.dev,已 gitignore) +# 取值参考 xiaoqu-franchisee/pom.xml dev profile +M0_DB_USERNAME=root +M0_DB_PASSWORD= +M1_DB_USERNAME=root +M1_DB_PASSWORD= +M2_DB_USERNAME=root +M2_DB_PASSWORD= +SVC_DB_USERNAME=root +SVC_DB_PASSWORD= +REDIS_PASSWORD= diff --git a/xiaoqu-agent-service/deploy/deploy.sh b/xiaoqu-agent-service/deploy/deploy.sh new file mode 100755 index 0000000..8e86c20 --- /dev/null +++ b/xiaoqu-agent-service/deploy/deploy.sh @@ -0,0 +1,97 @@ +#!/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 + 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 -DskipTests + 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