Files
ccdi/bin/restart_java_backend.sh
2026-04-20 11:24:18 +08:00

266 lines
6.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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"
PID_FILE="$LOG_DIR/backend-java.pid"
TARGET_DIR="$ROOT_DIR/ruoyi-admin/target"
JAR_NAME="ruoyi-admin.jar"
SERVER_PORT=62318
STOP_WAIT_SECONDS=30
APP_MARKER="-Dccdi.backend.root=$ROOT_DIR"
JAVA_OPTS="$APP_MARKER -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError"
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
}
is_managed_backend_pid() {
pid="$1"
if [ -z "${pid:-}" ] || ! kill -0 "$pid" 2>/dev/null; then
return 1
fi
args=$(ps -o args= -p "$pid" 2>/dev/null || true)
if [ -z "${args:-}" ]; then
return 1
fi
case "$args" in
*"$APP_MARKER"*"$JAR_NAME"*|*"$JAR_NAME"*"$APP_MARKER"*)
return 0
;;
esac
if [ -f "$PID_FILE" ]; then
file_pid=$(cat "$PID_FILE" 2>/dev/null || true)
if [ "${file_pid:-}" = "$pid" ]; then
case "$args" in
*"java"*"-jar"*"$JAR_NAME"*)
return 0
;;
esac
fi
fi
return 1
}
collect_pids() {
all_pids=""
if [ -f "$PID_FILE" ]; then
file_pid=$(cat "$PID_FILE" 2>/dev/null || true)
if [ -n "${file_pid:-}" ] && is_managed_backend_pid "$file_pid"; then
all_pids="$all_pids $file_pid"
fi
fi
marker_pids=$(pgrep -f -- "$APP_MARKER" 2>/dev/null || true)
if [ -n "${marker_pids:-}" ]; then
for pid in $marker_pids; do
if is_managed_backend_pid "$pid"; then
all_pids="$all_pids $pid"
fi
done
fi
port_pids=$(lsof -tiTCP:"$SERVER_PORT" -sTCP:LISTEN 2>/dev/null || true)
if [ -n "${port_pids:-}" ]; then
for pid in $port_pids; do
if is_managed_backend_pid "$pid"; then
all_pids="$all_pids $pid"
fi
done
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"
if [ ! -f "$TARGET_DIR/$JAR_NAME" ]; then
log_error "未找到打包产物: $TARGET_DIR/$JAR_NAME"
exit 1
fi
(
cd "$TARGET_DIR"
nohup java $JAVA_OPTS -jar "$JAR_NAME" >> "$CONSOLE_LOG" 2>&1 &
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"
return 0
fi
port_pids=$(lsof -tiTCP:"$SERVER_PORT" -sTCP:LISTEN 2>/dev/null || true)
if [ -n "${port_pids:-}" ]; then
log_info "未发现脚本托管的后端进程,但端口 $SERVER_PORT 被其他进程占用: $port_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 ps
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 "$@"