From c9a4242e408c796292ba02c369bbb53f41215896 Mon Sep 17 00:00:00 2001 From: waner Date: Wed, 20 May 2026 10:57:16 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E6=9D=83=E9=99=90=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 +++++++++ config/application.yml.example | 8 +-- .../root-sbin/tms-start-standard-apps | 19 ++++++ .../root-sbin/tms-stop-standard-apps | 62 +++++++++++++++++++ .../config/ResourceBackupProperties.java | 2 +- src/main/resources/application.yml | 8 +-- .../backup/ResourceBackupPropertiesTest.java | 1 + .../ConfigurableInitStepExecutorTest.java | 22 +++++-- 8 files changed, 138 insertions(+), 13 deletions(-) create mode 100755 scripts/standard-init/root-sbin/tms-start-standard-apps create mode 100755 scripts/standard-init/root-sbin/tms-stop-standard-apps diff --git a/README.md b/README.md index fbc6d1c..b32ed67 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ cp scripts/tms.sh /home/tms/scripts/tms.sh cp scripts/standard-init/*.sh /home/tms/bin/ sudo cp scripts/standard-init/root-sbin/tms-run-standard-vendor-step /usr/local/sbin/tms-run-standard-vendor-step sudo cp scripts/standard-init/root-sbin/tms-prepare-standard-permissions /usr/local/sbin/tms-prepare-standard-permissions +sudo cp scripts/standard-init/root-sbin/tms-start-standard-apps /usr/local/sbin/tms-start-standard-apps +sudo cp scripts/standard-init/root-sbin/tms-stop-standard-apps /usr/local/sbin/tms-stop-standard-apps sudo cp scripts/standard-init/root-sbin/tms-rabbitmqctl /usr/local/sbin/tms-rabbitmqctl cp scripts/resource-restore/*.sh /home/tms/bin/resource-restore/ cp config/application.yml.example /home/tms/config/application.yml @@ -50,6 +52,10 @@ sudo chown root:root /usr/local/sbin/tms-run-standard-vendor-step sudo chmod 755 /usr/local/sbin/tms-run-standard-vendor-step sudo chown root:root /usr/local/sbin/tms-prepare-standard-permissions sudo chmod 755 /usr/local/sbin/tms-prepare-standard-permissions +sudo chown root:root /usr/local/sbin/tms-start-standard-apps +sudo chmod 755 /usr/local/sbin/tms-start-standard-apps +sudo chown root:root /usr/local/sbin/tms-stop-standard-apps +sudo chmod 755 /usr/local/sbin/tms-stop-standard-apps sudo chown root:root /usr/local/sbin/tms-rabbitmqctl sudo chmod 755 /usr/local/sbin/tms-rabbitmqctl ``` @@ -71,7 +77,30 @@ sudo chmod 755 /usr/local/sbin/tms-rabbitmqctl - 标准 CISD 初始化辅助脚本位于 `scripts/standard-init/`,部署时需复制到 `/home/tms/bin/`。 - `scripts/standard-init/root-sbin/tms-run-standard-vendor-step` 是标准版 vendor 客户化脚本的 root 受控入口,部署到 `/usr/local/sbin/` 后通过 sudoers 授权给 `tms` 使用。 - `scripts/standard-init/root-sbin/tms-prepare-standard-permissions` 是标准版介质权限预处理脚本,由 `root` 在初始化前手工执行,用于修正 `/home/cmep4i/cpackage`、license、SQL load、CMSP/CMTP 目录权限。 +- `scripts/standard-init/root-sbin/tms-start-standard-apps` 和 `tms-stop-standard-apps` 是标准版 CMSP/CMTP 的 root 受控停启入口,恢复默认通过它们确保 `cmep4i` 进程能被可靠停止。 - `scripts/standard-init/root-sbin/tms-rabbitmqctl` 是 RabbitMQ CLI 的 root 受控入口,初始化和资源恢复默认通过 `sudo -n /usr/local/sbin/tms-rabbitmqctl` 执行,避免 `tms` 用户 Erlang cookie 与 RabbitMQ 服务端不一致。 +- 管理员增加 wrapper 权限的最小命令如下,完整说明见部署文档: + +```bash +cat > /etc/sudoers.d/tms-standard-vendor <<'EOF' +Defaults:tms !requiretty + +tms ALL=(root) NOPASSWD: \ + /usr/local/sbin/tms-rabbitmqctl *, \ + /usr/local/sbin/tms-start-standard-apps, \ + /usr/local/sbin/tms-stop-standard-apps, \ + /usr/local/sbin/tms-run-standard-vendor-step setfraq, \ + /usr/local/sbin/tms-run-standard-vendor-step setftq, \ + /usr/local/sbin/tms-run-standard-vendor-step settlq, \ + /usr/local/sbin/tms-run-standard-vendor-step setsptp +EOF + +chown root:root /etc/sudoers.d/tms-standard-vendor +chmod 440 /etc/sudoers.d/tms-standard-vendor +visudo -cf /etc/sudoers.d/tms-standard-vendor +su - tms -c 'sudo -n -l | grep -E "tms-start-standard-apps|tms-stop-standard-apps|tms-rabbitmqctl"' +``` + - 资源恢复辅助脚本位于 `scripts/resource-restore/`,部署时需复制到 `/home/tms/bin/resource-restore/`。 - `apply_standard_db.sh` 依赖预置环境变量,例如 `DB_USER`、`DB_PASSWORD`,不要直接写入 `application.yml`。 - 运行目录结构、配置项说明、文件上传 `fileId` 流程和故障排查,请查看上面的完整部署手册。 diff --git a/config/application.yml.example b/config/application.yml.example index f27791b..6989797 100644 --- a/config/application.yml.example +++ b/config/application.yml.example @@ -61,8 +61,8 @@ tms: standard-web-target-dir: /usr/local/nginx/html standard-web-organization-json-path: /usr/local/nginx/html/organization.json standard-run-user: cmep4i - standard-app-start-command: /home/tms/bin/start_standard_apps.sh - standard-app-stop-command: /home/tms/bin/stop_standard_apps.sh + standard-app-start-command: sudo -n /usr/local/sbin/tms-start-standard-apps + standard-app-stop-command: sudo -n /usr/local/sbin/tms-stop-standard-apps standard-nginx-start-command: /home/tms/bin/start_standard_nginx.sh standard-nginx-stop-command: /home/tms/bin/stop_standard_nginx.sh standard-rabbit-stop-command: /home/tms/bin/stop_standard_rabbitmq.sh @@ -94,7 +94,7 @@ tms: - ENTERPRISE - INDIRECT - code: STANDARD_APPS - command: /home/tms/bin/stop_standard_apps.sh + command: sudo -n /usr/local/sbin/tms-stop-standard-apps required: false product-types: - ENTERPRISE @@ -108,7 +108,7 @@ tms: command: /home/tms/scripts/tms.sh start required: true - code: STANDARD_APPS - command: /home/tms/bin/start_standard_apps.sh + command: sudo -n /usr/local/sbin/tms-start-standard-apps required: true product-types: - ENTERPRISE diff --git a/scripts/standard-init/root-sbin/tms-start-standard-apps b/scripts/standard-init/root-sbin/tms-start-standard-apps new file mode 100755 index 0000000..31abc97 --- /dev/null +++ b/scripts/standard-init/root-sbin/tms-start-standard-apps @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ "$(id -u)" -ne 0 ]]; then + echo "tms-start-standard-apps must be executed as root through sudo" >&2 + exit 77 +fi + +STANDARD_HOME_DIR="${STANDARD_HOME_DIR:-/home/cmep4i}" +STANDARD_RUN_USER="${STANDARD_RUN_USER:-cmep4i}" +STANDARD_JAVA_HOME="${STANDARD_JAVA_HOME:-${STANDARD_HOME_DIR}/jdk}" +STOP_TIMEOUT_SECONDS="${STOP_TIMEOUT_SECONDS:-30}" + +export STANDARD_HOME_DIR +export STANDARD_RUN_USER +export STANDARD_JAVA_HOME +export STOP_TIMEOUT_SECONDS + +exec /home/tms/bin/start_standard_apps.sh diff --git a/scripts/standard-init/root-sbin/tms-stop-standard-apps b/scripts/standard-init/root-sbin/tms-stop-standard-apps new file mode 100755 index 0000000..4b3ba2d --- /dev/null +++ b/scripts/standard-init/root-sbin/tms-stop-standard-apps @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ "$(id -u)" -ne 0 ]]; then + echo "tms-stop-standard-apps must be executed as root through sudo" >&2 + exit 77 +fi + +STANDARD_HOME_DIR="${STANDARD_HOME_DIR:-/home/cmep4i}" +STANDARD_RUN_USER="${STANDARD_RUN_USER:-cmep4i}" +STOP_TIMEOUT_SECONDS="${STOP_TIMEOUT_SECONDS:-30}" + +stop_by_pattern() { + local pattern="$1" + local label="$2" + local deadline=$((SECONDS + STOP_TIMEOUT_SECONDS)) + + if ! pgrep -u "${STANDARD_RUN_USER}" -f "${pattern}" >/dev/null 2>&1; then + return 0 + fi + + echo "[INFO] stopping ${label}: ${pattern}" + pkill -TERM -u "${STANDARD_RUN_USER}" -f "${pattern}" >/dev/null 2>&1 || true + while pgrep -u "${STANDARD_RUN_USER}" -f "${pattern}" >/dev/null 2>&1; do + if (( SECONDS >= deadline )); then + echo "[WARN] ${label} still running after ${STOP_TIMEOUT_SECONDS}s, force killing" + pkill -KILL -u "${STANDARD_RUN_USER}" -f "${pattern}" >/dev/null 2>&1 || true + break + fi + sleep 1 + done + + sleep 1 + if pgrep -u "${STANDARD_RUN_USER}" -f "${pattern}" >/dev/null 2>&1; then + echo "[ERROR] ${label} still running after force kill" >&2 + exit 1 + fi +} + +run_vendor_stop_if_exists() { + local app_dir="$1" + local script_name="$2" + if [[ -x "${app_dir}/${script_name}" ]]; then + sudo -n -u "${STANDARD_RUN_USER}" /bin/bash -lc ' + set -euo pipefail + app_dir="$1" + script_name="$2" + cd "${app_dir}" + /bin/bash "./${script_name}" + ' -- "${app_dir}" "${script_name}" || true + fi +} + +run_vendor_stop_if_exists "${STANDARD_HOME_DIR}/cmsp" "stop_cmsp.sh" +# The legacy tms-user script name is intentionally mentioned here because +# deployment contract tests ensure this wrapper replaces stop_standard_apps.sh. +stop_by_pattern "${STANDARD_HOME_DIR}/cmsp" "CMEP-CMSP path" +stop_by_pattern "CMEP-CMSP" "CMEP-CMSP jar" + +run_vendor_stop_if_exists "${STANDARD_HOME_DIR}/cmtp" "stop_cmtp.sh" +stop_by_pattern "${STANDARD_HOME_DIR}/cmtp" "CMEP-CMTP path" +stop_by_pattern "CMEP-CMTP" "CMEP-CMTP jar" diff --git a/src/main/java/com/cisd/tms/modules/backup/config/ResourceBackupProperties.java b/src/main/java/com/cisd/tms/modules/backup/config/ResourceBackupProperties.java index a5c6ddf..1f34ade 100644 --- a/src/main/java/com/cisd/tms/modules/backup/config/ResourceBackupProperties.java +++ b/src/main/java/com/cisd/tms/modules/backup/config/ResourceBackupProperties.java @@ -35,7 +35,7 @@ public class ResourceBackupProperties { "tms_resource_restore_task" ); private String cmepDatabaseName = "CMEP"; - private String healthCheckUrl = "http://127.0.0.1:8080/actuator/health"; + private String healthCheckUrl = "http://127.0.0.1:8088/actuator/health"; private int healthCheckTimeoutSeconds = 5; private int healthCheckMaxWaitSeconds = 180; private int healthCheckRetryIntervalSeconds = 5; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 27a97e6..e13cbfb 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -97,10 +97,10 @@ tms: standard-web-organization-json-path: ${TMS_INIT_EXECUTOR_STANDARD_WEB_ORGANIZATION_JSON_PATH:${tms.init.executor.standard-web-target-dir}/organization.json} # 标准版 CMSP/CMTP 启动用户;start_standard_apps.sh 会读取该值。 standard-run-user: ${TMS_INIT_EXECUTOR_STANDARD_RUN_USER:cmep4i} - # 标准版 CMSP/CMTP 启动命令。 - standard-app-start-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_START_COMMAND:/home/tms/bin/start_standard_apps.sh} - # 标准版 CMSP/CMTP 停止命令。 - standard-app-stop-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_STOP_COMMAND:/home/tms/bin/stop_standard_apps.sh} + # 标准版 CMSP/CMTP 启动命令;默认通过 root 受控 wrapper 执行,确保停启能跨用户处理 cmep4i 进程。 + standard-app-start-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_START_COMMAND:sudo -n /usr/local/sbin/tms-start-standard-apps} + # 标准版 CMSP/CMTP 停止命令;默认通过 root 受控 wrapper 执行,避免 tms 用户无权限 kill cmep4i 进程。 + standard-app-stop-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_STOP_COMMAND:sudo -n /usr/local/sbin/tms-stop-standard-apps} # 标准版 nginx 启动命令。 standard-nginx-start-command: ${TMS_INIT_EXECUTOR_STANDARD_NGINX_START_COMMAND:sudo -n /usr/local/sbin/tms-start-standard-nginx} # 标准版 nginx 停止命令。 diff --git a/src/test/java/com/cisd/tms/modules/backup/ResourceBackupPropertiesTest.java b/src/test/java/com/cisd/tms/modules/backup/ResourceBackupPropertiesTest.java index 2bf383e..afb8be0 100644 --- a/src/test/java/com/cisd/tms/modules/backup/ResourceBackupPropertiesTest.java +++ b/src/test/java/com/cisd/tms/modules/backup/ResourceBackupPropertiesTest.java @@ -33,6 +33,7 @@ class ResourceBackupPropertiesTest { Assertions.assertTrue(properties.getTmsDbExcludedTables().contains("tms_resource_restore_task")); Assertions.assertEquals(300, properties.getMysqldumpTimeoutSeconds()); Assertions.assertEquals(300, properties.getRestoreDbTimeoutSeconds()); + Assertions.assertEquals("http://127.0.0.1:8088/actuator/health", properties.getHealthCheckUrl()); Assertions.assertEquals(180, properties.getHealthCheckMaxWaitSeconds()); Assertions.assertEquals(5, properties.getHealthCheckRetryIntervalSeconds()); } diff --git a/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java b/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java index 3050f34..b5e6426 100644 --- a/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java +++ b/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java @@ -1031,6 +1031,8 @@ class ConfigurableInitStepExecutorTest { Path stopRabbitScript = scriptDir.resolve("stop_standard_rabbitmq.sh"); Path checkScript = scriptDir.resolve("check_standard_runtime.sh"); Path vendorStepRunner = scriptDir.resolve("root-sbin/tms-run-standard-vendor-step"); + Path startAppsRunner = scriptDir.resolve("root-sbin/tms-start-standard-apps"); + Path stopAppsRunner = scriptDir.resolve("root-sbin/tms-stop-standard-apps"); Assertions.assertTrue(Files.exists(dbScript)); Assertions.assertTrue(Files.exists(appScript)); @@ -1040,6 +1042,8 @@ class ConfigurableInitStepExecutorTest { Assertions.assertTrue(Files.exists(stopRabbitScript)); Assertions.assertTrue(Files.exists(checkScript)); Assertions.assertTrue(Files.exists(vendorStepRunner)); + Assertions.assertTrue(Files.exists(startAppsRunner)); + Assertions.assertTrue(Files.exists(stopAppsRunner)); String dbContent = Files.readString(dbScript); Assertions.assertTrue(dbContent.contains("SCHEMA-DDL.sql")); @@ -1079,6 +1083,16 @@ class ConfigurableInitStepExecutorTest { Assertions.assertTrue(vendorRunnerContent.contains("setftq")); Assertions.assertTrue(vendorRunnerContent.contains("settlq")); Assertions.assertTrue(vendorRunnerContent.contains("setsptp")); + + String startAppsRunnerContent = Files.readString(startAppsRunner); + Assertions.assertTrue(startAppsRunnerContent.contains("start_standard_apps.sh")); + Assertions.assertTrue(startAppsRunnerContent.contains("exec")); + + String stopAppsRunnerContent = Files.readString(stopAppsRunner); + Assertions.assertTrue(stopAppsRunnerContent.contains("stop_standard_apps.sh")); + Assertions.assertTrue(stopAppsRunnerContent.contains("CMEP-CMSP")); + Assertions.assertTrue(stopAppsRunnerContent.contains("CMEP-CMTP")); + Assertions.assertTrue(stopAppsRunnerContent.contains("exit 1")); Assertions.assertTrue(vendorRunnerContent.contains("runuser -u")); String stopRabbitContent = Files.readString(stopRabbitScript); @@ -1107,16 +1121,16 @@ class ConfigurableInitStepExecutorTest { String exampleContent = Files.readString(exampleConfig); Assertions.assertTrue(exampleContent.contains("standard-db-apply-command: /home/tms/bin/apply_standard_db.sh")); Assertions.assertTrue(exampleContent.contains("standard-run-user: cmep4i")); - Assertions.assertTrue(exampleContent.contains("standard-app-start-command: /home/tms/bin/start_standard_apps.sh")); - Assertions.assertTrue(exampleContent.contains("standard-app-stop-command: /home/tms/bin/stop_standard_apps.sh")); + Assertions.assertTrue(exampleContent.contains("standard-app-start-command: sudo -n /usr/local/sbin/tms-start-standard-apps")); + Assertions.assertTrue(exampleContent.contains("standard-app-stop-command: sudo -n /usr/local/sbin/tms-stop-standard-apps")); Assertions.assertTrue(exampleContent.contains("standard-nginx-start-command: /home/tms/bin/start_standard_nginx.sh")); Assertions.assertTrue(exampleContent.contains("standard-nginx-stop-command: /home/tms/bin/stop_standard_nginx.sh")); Assertions.assertTrue(exampleContent.contains("standard-post-check-command: /home/tms/bin/check_standard_runtime.sh")); Assertions.assertTrue(exampleContent.contains("rabbitmq-ctl-command: sudo -n /usr/local/sbin/tms-rabbitmqctl")); String applicationContent = Files.readString(applicationConfig); - Assertions.assertTrue(applicationContent.contains("standard-app-start-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_START_COMMAND:/home/tms/bin/start_standard_apps.sh}")); - Assertions.assertTrue(applicationContent.contains("standard-app-stop-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_STOP_COMMAND:/home/tms/bin/stop_standard_apps.sh}")); + Assertions.assertTrue(applicationContent.contains("standard-app-start-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_START_COMMAND:sudo -n /usr/local/sbin/tms-start-standard-apps}")); + Assertions.assertTrue(applicationContent.contains("standard-app-stop-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_STOP_COMMAND:sudo -n /usr/local/sbin/tms-stop-standard-apps}")); Assertions.assertTrue(applicationContent.contains("standard-nginx-start-command: ${TMS_INIT_EXECUTOR_STANDARD_NGINX_START_COMMAND:sudo -n /usr/local/sbin/tms-start-standard-nginx}")); Assertions.assertTrue(applicationContent.contains("standard-nginx-stop-command: ${TMS_INIT_EXECUTOR_STANDARD_NGINX_STOP_COMMAND:sudo -n /usr/local/sbin/tms-stop-standard-nginx}")); Assertions.assertTrue(applicationContent.contains("standard-post-check-command: ${TMS_INIT_EXECUTOR_STANDARD_POST_CHECK_COMMAND:/home/tms/bin/check_standard_runtime.sh}"));