From a8e15e16d9451e6d623f0d817541c933f356be25 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Mon, 30 Mar 2026 17:28:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B6=E6=95=9B=E5=90=8E=E7=AB=AF=E9=87=8D?= =?UTF-8?q?=E5=90=AF=E8=84=9A=E6=9C=AC=E5=81=9C=E6=9C=BA=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 18436 -> 18436 bytes assets/员工账户.xlsx | Bin 0 -> 10780 bytes bin/restart_java_backend.sh | 59 ++++++++++++++---- ...-30-restart-java-backend-stop-scope-fix.md | 48 ++++++++++++++ .../test-restart-java-backend-stop-scope.sh | 57 +++++++++++++++++ .../scripts/test-restart-java-backend.sh | 4 +- 6 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 assets/员工账户.xlsx create mode 100644 docs/reports/implementation/2026-03-30-restart-java-backend-stop-scope-fix.md create mode 100644 docs/tests/scripts/test-restart-java-backend-stop-scope.sh diff --git a/.DS_Store b/.DS_Store index 04c8fe28e66e6a5a0f3d4be68933dbeec7be0b5a..0adf18c3e6764b2004c788d8feb5ad0b72a57590 100644 GIT binary patch delta 479 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/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:-}" ] && kill -0 "$file_pid" 2>/dev/null; then + if [ -n "${file_pid:-}" ] && is_managed_backend_pid "$file_pid"; 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" + 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 unique_pids="" @@ -155,6 +185,12 @@ 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 @@ -190,6 +226,7 @@ main() { ensure_command mvn ensure_command lsof ensure_command pgrep + ensure_command ps ensure_command tail action="${1:-restart}" diff --git a/docs/reports/implementation/2026-03-30-restart-java-backend-stop-scope-fix.md b/docs/reports/implementation/2026-03-30-restart-java-backend-stop-scope-fix.md new file mode 100644 index 00000000..1d845393 --- /dev/null +++ b/docs/reports/implementation/2026-03-30-restart-java-backend-stop-scope-fix.md @@ -0,0 +1,48 @@ +# 后端启停脚本停机范围收敛实施记录 + +## 修改目标 + +- 修复 `bin/restart_java_backend.sh` 在执行 `stop` / `restart` 时可能误杀非脚本托管 Java 进程的问题 +- 保持现有 `java -jar ruoyi-admin.jar` 启动方式不变,仅收敛停机识别范围 + +## 根因分析 + +- 原脚本在 `stop_backend()` 中通过 `collect_pids()` 同时合并以下来源后统一执行 `kill`: + - `logs/backend-java.pid` 中记录的 PID + - 监听 `62318` 端口的进程 + - 命令行中包含 `ruoyi-admin.jar` 关键字的进程 +- 该逻辑会把“不是由本脚本拉起、但恰好占用端口或命中关键字”的外部进程也纳入停机列表,导致关闭后端时误杀其他进程。 + +## 修改内容 + +- 调整 [`bin/restart_java_backend.sh`](/Users/wkc/Desktop/ccdi/ccdi/bin/restart_java_backend.sh) + - 新增 `APP_MARKER="-Dccdi.backend.root=$ROOT_DIR"`,启动时把仓库根路径标记写入 Java 启动参数 + - 新增 `is_managed_backend_pid()`,只把带有脚本标记的 Java 进程视为脚本托管进程 + - `collect_pids()` 改为仅收集: + - `PID_FILE` 中仍存活且校验通过的进程 + - 命令行里带脚本标记的进程 + - 不再把“端口占用者”或“仅命中 jar 名的进程”直接纳入停机目标 + - `status` 增加提示:若未发现脚本托管进程,但 `62318` 被其他进程占用,会明确输出占用 PID,避免误判为脚本自身后端 +- 调整 [`docs/tests/scripts/test-restart-java-backend.sh`](/Users/wkc/Desktop/ccdi/ccdi/docs/tests/scripts/test-restart-java-backend.sh) + - 增加对 `APP_MARKER` 的静态校验,防止后续移除托管标记 +- 新增 [`docs/tests/scripts/test-restart-java-backend-stop-scope.sh`](/Users/wkc/Desktop/ccdi/ccdi/docs/tests/scripts/test-restart-java-backend-stop-scope.sh) + - 在临时目录复制启停脚本 + - 启动一个未托管的外部占口进程 + - 验证执行 `stop` 后该外部进程仍然存活,防止回归到误杀外部进程的行为 + +## 验证记录 + +- 执行 `sh docs/tests/scripts/test-restart-java-backend-stop-scope.sh` + - 结果:通过 + - 说明:已验证 `stop` 不会误杀未由脚本托管的占口进程 +- 执行 `sh docs/tests/scripts/test-restart-java-backend.sh` + - 结果:通过 + - 说明:已验证脚本仍使用 `java -jar ruoyi-admin.jar` 启动,且保留托管进程标记 +- 执行 `sh -n bin/restart_java_backend.sh` + - 结果:通过 + - 说明:脚本语法正确 + +## 影响范围 + +- 仅影响本地后端启停辅助脚本与对应测试脚本 +- 不涉及 Java 业务代码、数据库、前端页面及 Mock 服务逻辑 diff --git a/docs/tests/scripts/test-restart-java-backend-stop-scope.sh b/docs/tests/scripts/test-restart-java-backend-stop-scope.sh new file mode 100644 index 00000000..73a78f2a --- /dev/null +++ b/docs/tests/scripts/test-restart-java-backend-stop-scope.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +set -eu + +ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/../../.." && pwd) +SOURCE_SCRIPT="$ROOT_DIR/bin/restart_java_backend.sh" +TMP_DIR=$(mktemp -d) +TEST_ROOT="$TMP_DIR/app" +TEST_BIN_DIR="$TEST_ROOT/bin" +TEST_LOG_DIR="$TEST_ROOT/logs" +TEST_PORT=62481 +EXTERNAL_PID="" + +cleanup() { + if [ -n "${EXTERNAL_PID:-}" ] && kill -0 "$EXTERNAL_PID" 2>/dev/null; then + kill "$EXTERNAL_PID" 2>/dev/null || true + wait "$EXTERNAL_PID" 2>/dev/null || true + fi + rm -rf "$TMP_DIR" +} + +trap cleanup EXIT INT TERM + +mkdir -p "$TEST_BIN_DIR" "$TEST_LOG_DIR" +cp "$SOURCE_SCRIPT" "$TEST_BIN_DIR/restart_java_backend.sh" +chmod +x "$TEST_BIN_DIR/restart_java_backend.sh" + +python3 -m http.server "$TEST_PORT" --bind 127.0.0.1 > "$TMP_DIR/external.log" 2>&1 & +EXTERNAL_PID=$! + +sleep 1 + +if ! kill -0 "$EXTERNAL_PID" 2>/dev/null; then + echo "失败: 未能启动外部占口进程" + exit 1 +fi + +python3 - "$TEST_BIN_DIR/restart_java_backend.sh" "$TEST_PORT" <<'PY' +from pathlib import Path +import sys + +script_path = Path(sys.argv[1]) +port = sys.argv[2] +content = script_path.read_text(encoding="utf-8") +content = content.replace("SERVER_PORT=62318", f"SERVER_PORT={port}") +script_path.write_text(content, encoding="utf-8") +PY + +echo "[检查] stop 不能误杀未由脚本托管的占口进程" +sh "$TEST_BIN_DIR/restart_java_backend.sh" stop >/dev/null 2>&1 || true + +if ! kill -0 "$EXTERNAL_PID" 2>/dev/null; then + echo "失败: stop 误杀了未托管的外部进程" + exit 1 +fi + +echo "通过" diff --git a/docs/tests/scripts/test-restart-java-backend.sh b/docs/tests/scripts/test-restart-java-backend.sh index c57c4f95..53f0fc09 100644 --- a/docs/tests/scripts/test-restart-java-backend.sh +++ b/docs/tests/scripts/test-restart-java-backend.sh @@ -27,8 +27,8 @@ if grep -Fq 'spring-boot:run' "$SCRIPT_FILE"; then exit 1 fi -if ! grep -Fq 'APP_KEYWORD="$JAR_NAME"' "$SCRIPT_FILE"; then - echo "失败: 进程识别未切换到 jar 关键字" +if ! grep -Fq 'APP_MARKER="-Dccdi.backend.root=$ROOT_DIR"' "$SCRIPT_FILE"; then + echo "失败: 未为脚本托管的后端进程写入唯一标记" exit 1 fi