From 68a7304d46420ae1e5604ea42e640086abb69d5f Mon Sep 17 00:00:00 2001 From: xuans Date: Sun, 27 Sep 2026 00:35:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=AE=E5=BD=95=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=A5=97=E6=8E=A5=E5=AD=97=E5=81=9C=E6=AD=A2=E5=90=8E?= =?UTF-8?q?=E9=98=BB=E6=AD=A2=E5=AE=89=E8=A3=85=E5=99=A8=E5=8D=87=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/admin/installer_test.go | 64 ++++++++++++++++++++++++ deploy/install-linux.sh | 3 ++ 2 files changed, 67 insertions(+) diff --git a/backend/internal/admin/installer_test.go b/backend/internal/admin/installer_test.go index 1746f3a..235b7cf 100644 --- a/backend/internal/admin/installer_test.go +++ b/backend/internal/admin/installer_test.go @@ -3,12 +3,76 @@ package admin import ( "bufio" "os" + "os/exec" "path/filepath" "regexp" "strings" "testing" ) +func TestLinuxInstallerStoppedUnitStates(t *testing.T) { + bash, err := exec.LookPath("bash") + if err != nil { + t.Skip(err) + } + data, err := os.ReadFile(filepath.Join("..", "..", "..", "deploy", "install-linux.sh")) + if err != nil { + t.Fatal(err) + } + content := string(data) + start := strings.Index(content, "ensure_services_stopped() {") + if start < 0 { + t.Fatal("ensure_services_stopped") + } + end := strings.Index(content[start:], "\n}\n") + if end < 0 { + t.Fatal("ensure_services_stopped") + } + guard := content[start : start+end+3] + stopped := "LoadState=loaded\nActiveState=inactive\nSubState=dead\nControlPID=0\nJob=\n" + for _, tc := range []struct { + name string + unit string + properties string + allowed bool + }{ + {"socket-missing-main-pid", "Scert-storage.socket", stopped, true}, + {"socket-zero-main-pid", "Scert-storage.socket", stopped + "MainPID=0\n", true}, + {"socket-active", "Scert-storage.socket", strings.ReplaceAll(strings.ReplaceAll(stopped, "inactive", "active"), "dead", "listening"), false}, + {"socket-control-process", "Scert-storage.socket", strings.ReplaceAll(stopped, "ControlPID=0", "ControlPID=52"), false}, + {"socket-missing-control-pid", "Scert-storage.socket", strings.ReplaceAll(stopped, "ControlPID=0\n", ""), false}, + {"socket-pending-job", "Scert-storage.socket", strings.ReplaceAll(stopped, "Job=", "Job=7"), false}, + {"socket-missing-job", "Scert-storage.socket", strings.ReplaceAll(stopped, "Job=\n", ""), false}, + {"socket-nonzero-main-pid", "Scert-storage.socket", stopped + "MainPID=51\n", false}, + {"service-missing-main-pid", "Scert.service", stopped, false}, + {"admin-missing-main-pid", "Scert-admin.service", stopped, false}, + {"storage-missing-main-pid", "Scert-storage.service", stopped, false}, + {"service-stopped", "Scert.service", stopped + "MainPID=0\n", true}, + } { + t.Run(tc.name, func(t *testing.T) { + script := `set -Eeuo pipefail +fail() { printf '%s\n' "$1" >&2; exit 1; } +systemctl() { + [[ "$1" == show ]] || exit 97 + if [[ "$2" == "$TEST_UNIT" ]]; then + printf '%s' "$TEST_PROPERTIES" + else + printf '%s' "$TEST_STOPPED" + [[ "$2" == *.socket ]] || printf 'MainPID=0\n' + fi + return 0 +} +` + guard + "\nensure_services_stopped\n" + command := exec.Command(bash, "--noprofile", "--norc", "-c", script) + command.Env = append(os.Environ(), "TEST_UNIT="+tc.unit, "TEST_PROPERTIES="+tc.properties, "TEST_STOPPED="+stopped) + output, err := command.CombinedOutput() + if (err == nil) != tc.allowed { + t.Fatalf("allowed=%t, err=%v, output=%s", tc.allowed, err, output) + } + }) + } +} + func TestLinuxInstallerPolicy(t *testing.T) { installerPath := filepath.Join("..", "..", "..", "deploy", "install-linux.sh") data, err := os.ReadFile(installerPath) diff --git a/deploy/install-linux.sh b/deploy/install-linux.sh index 299d283..85adc96 100644 --- a/deploy/install-linux.sh +++ b/deploy/install-linux.sh @@ -292,6 +292,9 @@ ensure_services_stopped() { loaded:inactive:dead|loaded:failed:failed|not-found:inactive:dead) ;; *) fail "升级或安装前必须确认 $unit 已停止,当前状态:$load_state/$active_state/$sub_state" ;; esac + if [[ "$unit" == *.socket && -z "$main_pid" ]]; then + main_pid="0" + fi [[ "$main_pid" == "0" && "$control_pid" == "0" && -z "$job" ]] || \ fail "$unit 仍有进程、排队任务或缺失状态,拒绝安装" done