#!/usr/bin/env bash set -Eeuo pipefail # 将 deploy.sh 和 bms-admin.jar 放在应用目录中,然后执行: # bash deploy.sh start|stop|restart|status # 服务使用当前执行用户运行,控制台输出追加到 logs/console.log。 APP_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" JAR_NAME="bms-admin.jar" JAR_PATH="$APP_DIR/$JAR_NAME" LOG_DIR="$APP_DIR/logs" CONSOLE_LOG="$LOG_DIR/console.log" JAVA_BIN="/www/server/java/jdk-17.0.8/bin/java" usage() { echo "用法:bash deploy.sh {start|stop|restart|status}" } # 精确匹配由本目录启动的 bms-admin.jar,避免误停 ES 或其他 Java 服务。 find_app_pids() { local pid arg jar_arg cwd i local -a args while read -r pid; do [[ -r "/proc/$pid/cmdline" ]] || continue args=() while IFS= read -r -d '' arg; do args+=("$arg") done < "/proc/$pid/cmdline" jar_arg="" for ((i = 1; i + 1 < ${#args[@]}; i++)); do if [[ "${args[i]}" == "-jar" ]]; then jar_arg="${args[i + 1]}" break fi done case "$jar_arg" in "$JAR_PATH") echo "$pid" ;; "$JAR_NAME"|"./$JAR_NAME") cwd="$(readlink -f "/proc/$pid/cwd" 2>/dev/null || true)" [[ "$cwd" == "$APP_DIR" ]] && echo "$pid" || true ;; esac done < <(pgrep -x java || true) } resolve_java() { if [[ ! -x "$JAVA_BIN" ]]; then JAVA_BIN="$(command -v java || true)" fi if [[ -z "$JAVA_BIN" || ! -x "$JAVA_BIN" ]]; then echo "错误:找不到 Java。" return 1 fi } start_app() { local pids pids="$(find_app_pids)" if [[ -n "$pids" ]]; then echo "$JAR_NAME 已在运行,PID: $(tr '\n' ' ' <<< "$pids")" return 0 fi if [[ ! -f "$JAR_PATH" ]]; then echo "错误:找不到 $JAR_PATH" return 1 fi resolve_java || return 1 mkdir -p "$LOG_DIR" touch "$CONSOLE_LOG" echo "以 $(id -un) 用户启动 $JAR_NAME(prod)……" nohup "$JAVA_BIN" -jar "$JAR_PATH" --spring.profiles.active=prod >> "$CONSOLE_LOG" 2>&1 & sleep 2 pids="$(find_app_pids)" if [[ -z "$pids" ]]; then echo "启动失败,最近日志如下:" tail -n 50 "$CONSOLE_LOG" || true return 1 fi echo "启动成功,PID: $(tr '\n' ' ' <<< "$pids")" echo "实时日志:tail -f $CONSOLE_LOG" } stop_app() { local pids pid remaining pids="$(find_app_pids)" if [[ -z "$pids" ]]; then echo "$JAR_NAME 当前未运行。" return 0 fi echo "正在停止 $JAR_NAME,PID: $(tr '\n' ' ' <<< "$pids")" while read -r pid; do [[ -n "$pid" ]] && kill -TERM "$pid" 2>/dev/null || true done <<< "$pids" for _ in {1..30}; do [[ -z "$(find_app_pids)" ]] && break sleep 1 done remaining="$(find_app_pids)" if [[ -n "$remaining" ]]; then echo "服务未在 30 秒内退出,强制停止 PID: $(tr '\n' ' ' <<< "$remaining")" while read -r pid; do [[ -n "$pid" ]] && kill -KILL "$pid" 2>/dev/null || true done <<< "$remaining" sleep 1 fi remaining="$(find_app_pids)" if [[ -n "$remaining" ]]; then echo "错误:服务仍在运行,PID: $(tr '\n' ' ' <<< "$remaining");请检查执行用户和进程权限。" return 1 fi echo "$JAR_NAME 已停止。" } show_status() { local pids pids="$(find_app_pids)" if [[ -n "$pids" ]]; then echo "$JAR_NAME 正在运行,PID: $(tr '\n' ' ' <<< "$pids")" else echo "$JAR_NAME 当前未运行。" fi } case "${1:-}" in start) start_app ;; stop) stop_app ;; restart) stop_app && start_app ;; status) show_status ;; *) usage exit 2 ;; esac