#!/bin/bash # ============================================ # 中华药典 AI Agent — Java 后端部署脚本 # 用法: ./java-deploy.sh {start|stop|restart|status|logs|build|deploy} # ============================================ set -e APP_DIR="/opt/pharmacopoeia-ai/backend-java" PROJECT_DIR="/opt/pharmacopoeia-ai" JAR_FILE="$APP_DIR/target/pharmacopoeia-ai-1.0.0.jar" LOG_DIR="/var/log/pharmacopoeia" PID_FILE="$APP_DIR/app.pid" # 加载 .env 环境变量 load_env() { if [ -f "$PROJECT_DIR/.env" ]; then set -a source "$PROJECT_DIR/.env" set +a fi } load_env mkdir -p "$LOG_DIR" # ---- 服务端口 ---- PORT=${SERVER_PORT:-9000} HEALTH_URL="http://localhost:${PORT}/health" # ============================================ # 通用函数 # ============================================ running() { [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null } get_pid() { cat "$PID_FILE" 2>/dev/null || echo "N/A" } health_check() { curl -sf "$HEALTH_URL" > /dev/null 2>&1 } # ============================================ # 启动 # ============================================ start() { if running; then echo "⚠️ 后端已在运行中 (PID: $(get_pid))" curl -sf "$HEALTH_URL" | python3 -m json.tool 2>/dev/null || true return 0 fi # 自动编译(如果 JAR 不存在) if [ ! -f "$JAR_FILE" ]; then echo "📦 JAR 不存在,正在编译..." cd "$APP_DIR" mvn clean package -DskipTests -q echo "✅ 编译完成" fi echo "🚀 启动后端..." cd "$APP_DIR" JVM_OPTS="-Xms512m -Xmx2g" JVM_OPTS="$JVM_OPTS -XX:+UseG1GC" JVM_OPTS="$JVM_OPTS -Dfile.encoding=UTF-8" JVM_OPTS="$JVM_OPTS -Djava.security.egd=file:/dev/./urandom" nohup java $JVM_OPTS -jar "$JAR_FILE" \ --server.port="$PORT" \ >> "$LOG_DIR/backend.log" 2>&1 & echo $! > "$PID_FILE" echo " PID: $(get_pid)" # 等启动完成 echo -n " 等待启动" for i in $(seq 1 30); do if health_check 2>/dev/null; then echo "" echo "✅ 启动成功!" curl -sf "$HEALTH_URL" | python3 -m json.tool 2>/dev/null || true return 0 fi echo -n "." sleep 1 done echo "" echo "❌ 启动超时,查看日志:" tail -30 "$LOG_DIR/backend.log" rm -f "$PID_FILE" return 1 } # ============================================ # 停止 # ============================================ stop() { if ! running; then echo "后端未运行" rm -f "$PID_FILE" return 0 fi PID=$(get_pid) echo "🛑 停止后端 (PID: $PID)..." kill "$PID" for i in $(seq 1 30); do if ! kill -0 "$PID" 2>/dev/null; then echo "✅ 已停止" rm -f "$PID_FILE" return 0 fi sleep 1 done echo "⚠️ 超时,强制终止..." kill -9 "$PID" 2>/dev/null || true rm -f "$PID_FILE" echo "✅ 已强制停止" } # ============================================ # 重启 # ============================================ restart() { echo "⏳ 重启后端..." stop sleep 2 start } # ============================================ # 状态 # ============================================ status() { echo "========================================" echo " 中华药典 AI — Java 后端" echo "========================================" if running; then echo " 状态: ✅ 运行中" echo " PID: $(get_pid)" echo " 端口: $PORT" echo "" curl -sf "$HEALTH_URL" | python3 -m json.tool 2>/dev/null || echo " (健康检查无响应)" else echo " 状态: ❌ 未运行" fi echo "" echo " 日志: $LOG_DIR/backend.log" echo "========================================" } # ============================================ # 日志 # ============================================ logs() { if [ "$1" = "-f" ]; then tail -f "$LOG_DIR/backend.log" else echo "=== 最近 100 行日志 ===" tail -${1:-100} "$LOG_DIR/backend.log" fi } # ============================================ # 编译 # ============================================ build() { echo "📦 拉取最新代码..." cd "$PROJECT_DIR" git pull echo "🔨 编译打包..." cd "$APP_DIR" mvn clean package -DskipTests -q if [ -f "$JAR_FILE" ]; then echo "✅ 编译成功: $JAR_FILE" ls -lh "$JAR_FILE" else echo "❌ 编译失败" return 1 fi } # ============================================ # 一键部署(拉代码 → 编译 → 重启) # ============================================ deploy() { echo "========================================" echo " 一键部署" echo "========================================" echo "" echo "📥 拉取代码..." cd "$PROJECT_DIR" git pull echo "" echo "🔨 编译打包..." cd "$APP_DIR" mvn clean package -DskipTests -q if [ ! -f "$JAR_FILE" ]; then echo "❌ 编译失败,取消部署" return 1 fi echo "✅ 编译完成: $(ls -lh "$JAR_FILE" | awk '{print $5}')" echo "" restart } # ============================================ # 入口 # ============================================ case "${1:-start}" in start) start ;; stop) stop ;; restart) restart ;; status) status ;; logs) logs "${2:-100}" ;; logf) logs -f ;; build) build ;; deploy) deploy ;; help|--help|-h) echo "用法: $0 {start|stop|restart|status|logs|logf|build|deploy}" echo "" echo " start 启动后端" echo " stop 停止后端" echo " restart 重启后端" echo " status 查看状态" echo " logs 查看最近 100 行日志" echo " logf 实时跟踪日志" echo " build 拉代码 + 编译" echo " deploy 拉代码 + 编译 + 重启(一键上线)" exit 0 ;; *) echo "用法: $0 {start|stop|restart|status|logs|logf|build|deploy}" exit 1 ;; esac