Files
xiaoqu_mcp_service/xiaoqu-agent-service/deploy/deploy.sh
T

104 lines
3.0 KiB
Bash
Executable File

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