2026-03-19 16:38:20 +08:00
|
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
|
|
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
|
|
|
|
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
|
|
|
|
|
LOG_DIR="$ROOT_DIR/logs"
|
|
|
|
|
|
CONSOLE_LOG="$LOG_DIR/backend-console.log"
|
2026-03-19 17:08:07 +08:00
|
|
|
|
PID_FILE="$LOG_DIR/backend-java.pid"
|
|
|
|
|
|
TARGET_DIR="$ROOT_DIR/ruoyi-admin/target"
|
|
|
|
|
|
JAR_NAME="ruoyi-admin.jar"
|
2026-03-19 16:38:20 +08:00
|
|
|
|
SERVER_PORT=62318
|
|
|
|
|
|
STOP_WAIT_SECONDS=30
|
2026-03-19 17:08:07 +08:00
|
|
|
|
APP_KEYWORD="$JAR_NAME"
|
|
|
|
|
|
JAVA_OPTS="-Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError"
|
2026-03-19 16:38:20 +08:00
|
|
|
|
|
|
|
|
|
|
timestamp() {
|
|
|
|
|
|
date "+%Y-%m-%d %H:%M:%S"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
log_info() {
|
|
|
|
|
|
printf '[%s] %s\n' "$(timestamp)" "$1"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
log_error() {
|
|
|
|
|
|
printf '[%s] %s\n' "$(timestamp)" "$1" >&2
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
|
|
cat <<'EOF'
|
|
|
|
|
|
用法: ./bin/restart_java_backend.sh [start|stop|restart|status]
|
|
|
|
|
|
|
|
|
|
|
|
默认动作:
|
|
|
|
|
|
restart 重新构建后端并重启,随后持续输出运行日志
|
|
|
|
|
|
EOF
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ensure_command() {
|
|
|
|
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
|
|
|
|
log_error "缺少命令: $1"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
collect_pids() {
|
|
|
|
|
|
all_pids=""
|
|
|
|
|
|
|
|
|
|
|
|
if [ -f "$PID_FILE" ]; then
|
|
|
|
|
|
file_pid=$(cat "$PID_FILE" 2>/dev/null || true)
|
|
|
|
|
|
if [ -n "${file_pid:-}" ] && kill -0 "$file_pid" 2>/dev/null; then
|
|
|
|
|
|
all_pids="$all_pids $file_pid"
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
port_pids=$(lsof -tiTCP:"$SERVER_PORT" -sTCP:LISTEN 2>/dev/null || true)
|
|
|
|
|
|
if [ -n "${port_pids:-}" ]; then
|
|
|
|
|
|
all_pids="$all_pids $port_pids"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
app_pids=$(pgrep -f "$APP_KEYWORD" 2>/dev/null || true)
|
|
|
|
|
|
if [ -n "${app_pids:-}" ]; then
|
|
|
|
|
|
all_pids="$all_pids $app_pids"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
unique_pids=""
|
|
|
|
|
|
for pid in $all_pids; do
|
|
|
|
|
|
case " $unique_pids " in
|
|
|
|
|
|
*" $pid "*) ;;
|
|
|
|
|
|
*)
|
|
|
|
|
|
unique_pids="$unique_pids $pid"
|
|
|
|
|
|
;;
|
|
|
|
|
|
esac
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
printf '%s\n' "$(echo "$unique_pids" | xargs 2>/dev/null || true)"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
build_backend() {
|
|
|
|
|
|
log_info "开始构建后端: mvn -pl ruoyi-admin -am clean package -DskipTests"
|
|
|
|
|
|
(
|
|
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
|
|
mvn -pl ruoyi-admin -am clean package -DskipTests
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stop_backend() {
|
|
|
|
|
|
pids=$(collect_pids)
|
|
|
|
|
|
|
|
|
|
|
|
if [ -z "${pids:-}" ]; then
|
|
|
|
|
|
log_info "未发现运行中的后端进程"
|
|
|
|
|
|
rm -f "$PID_FILE"
|
|
|
|
|
|
return 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
log_info "准备停止后端进程: $pids"
|
|
|
|
|
|
for pid in $pids; do
|
|
|
|
|
|
kill -TERM "$pid" 2>/dev/null || true
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
remaining_pids="$pids"
|
|
|
|
|
|
elapsed=0
|
|
|
|
|
|
while [ -n "${remaining_pids:-}" ] && [ "$elapsed" -lt "$STOP_WAIT_SECONDS" ]; do
|
|
|
|
|
|
sleep 1
|
|
|
|
|
|
elapsed=$((elapsed + 1))
|
|
|
|
|
|
remaining_pids=""
|
|
|
|
|
|
for pid in $pids; do
|
|
|
|
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
|
|
|
|
remaining_pids="$remaining_pids $pid"
|
|
|
|
|
|
fi
|
|
|
|
|
|
done
|
|
|
|
|
|
remaining_pids=$(echo "$remaining_pids" | xargs 2>/dev/null || true)
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "${remaining_pids:-}" ]; then
|
|
|
|
|
|
log_info "仍有进程未退出,执行强制停止: $remaining_pids"
|
|
|
|
|
|
for pid in $remaining_pids; do
|
|
|
|
|
|
kill -KILL "$pid" 2>/dev/null || true
|
|
|
|
|
|
done
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
rm -f "$PID_FILE"
|
|
|
|
|
|
log_info "后端停止完成"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
start_backend() {
|
|
|
|
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
|
|
touch "$CONSOLE_LOG"
|
|
|
|
|
|
|
|
|
|
|
|
printf '\n===== %s restart =====\n' "$(timestamp)" >> "$CONSOLE_LOG"
|
|
|
|
|
|
|
|
|
|
|
|
log_info "开始启动后端,控制台日志输出到: $CONSOLE_LOG"
|
2026-03-19 17:08:07 +08:00
|
|
|
|
if [ ! -f "$TARGET_DIR/$JAR_NAME" ]; then
|
|
|
|
|
|
log_error "未找到打包产物: $TARGET_DIR/$JAR_NAME"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2026-03-19 16:38:20 +08:00
|
|
|
|
(
|
2026-03-19 17:08:07 +08:00
|
|
|
|
cd "$TARGET_DIR"
|
|
|
|
|
|
nohup java $JAVA_OPTS -jar "$JAR_NAME" >> "$CONSOLE_LOG" 2>&1 &
|
2026-03-19 16:38:20 +08:00
|
|
|
|
echo $! > "$PID_FILE"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
sleep 3
|
|
|
|
|
|
|
|
|
|
|
|
starter_pid=$(cat "$PID_FILE" 2>/dev/null || true)
|
|
|
|
|
|
if [ -z "${starter_pid:-}" ] || ! kill -0 "$starter_pid" 2>/dev/null; then
|
|
|
|
|
|
log_error "启动命令未保持运行,请检查日志: $CONSOLE_LOG"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
log_info "启动命令已提交,PID: $starter_pid"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_backend() {
|
|
|
|
|
|
pids=$(collect_pids)
|
|
|
|
|
|
if [ -n "${pids:-}" ]; then
|
|
|
|
|
|
log_info "后端正在运行,进程: $pids"
|
|
|
|
|
|
else
|
|
|
|
|
|
log_info "后端未运行"
|
|
|
|
|
|
fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
follow_logs() {
|
|
|
|
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
|
|
touch "$CONSOLE_LOG"
|
|
|
|
|
|
log_info "持续输出日志中,按 Ctrl+C 仅退出日志查看"
|
|
|
|
|
|
tail -n 200 -F "$CONSOLE_LOG"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
start_action() {
|
|
|
|
|
|
running_pids=$(collect_pids)
|
|
|
|
|
|
if [ -n "${running_pids:-}" ]; then
|
|
|
|
|
|
log_error "检测到已有后端进程在运行: $running_pids,请先执行 stop 或 restart"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
build_backend
|
|
|
|
|
|
start_backend
|
|
|
|
|
|
follow_logs
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
restart_action() {
|
|
|
|
|
|
build_backend
|
|
|
|
|
|
stop_backend
|
|
|
|
|
|
start_backend
|
|
|
|
|
|
follow_logs
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
main() {
|
|
|
|
|
|
ensure_command mvn
|
|
|
|
|
|
ensure_command lsof
|
|
|
|
|
|
ensure_command pgrep
|
|
|
|
|
|
ensure_command tail
|
|
|
|
|
|
|
|
|
|
|
|
action="${1:-restart}"
|
|
|
|
|
|
case "$action" in
|
|
|
|
|
|
start)
|
|
|
|
|
|
start_action
|
|
|
|
|
|
;;
|
|
|
|
|
|
stop)
|
|
|
|
|
|
stop_backend
|
|
|
|
|
|
;;
|
|
|
|
|
|
restart)
|
|
|
|
|
|
restart_action
|
|
|
|
|
|
;;
|
|
|
|
|
|
status)
|
|
|
|
|
|
status_backend
|
|
|
|
|
|
;;
|
|
|
|
|
|
-h|--help|help)
|
|
|
|
|
|
usage
|
|
|
|
|
|
;;
|
|
|
|
|
|
*)
|
|
|
|
|
|
usage
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
;;
|
|
|
|
|
|
esac
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
main "$@"
|