mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 00:38:28 +00:00
doctor: clean up legacy Linux gateway services (#21188)
* Doctor: clean up legacy Linux gateway services * doctor: refactor legacy service cleanup flow * doctor: fix legacy systemd cleanup map key typing * doctor: add changelog entry for legacy Linux service cleanup --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -5,7 +5,11 @@ import path from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveGatewayPort, resolveIsNixMode } from "../config/paths.js";
|
||||
import { findExtraGatewayServices, renderGatewayServiceCleanupHints } from "../daemon/inspect.js";
|
||||
import {
|
||||
findExtraGatewayServices,
|
||||
renderGatewayServiceCleanupHints,
|
||||
type ExtraGatewayService,
|
||||
} from "../daemon/inspect.js";
|
||||
import { renderSystemNodeWarning, resolveSystemNodeInfo } from "../daemon/runtime-paths.js";
|
||||
import {
|
||||
auditGatewayServiceConfig,
|
||||
@@ -13,6 +17,7 @@ import {
|
||||
SERVICE_AUDIT_CODES,
|
||||
} from "../daemon/service-audit.js";
|
||||
import { resolveGatewayService } from "../daemon/service.js";
|
||||
import { uninstallLegacySystemdUnits } from "../daemon/systemd.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
import { buildGatewayInstallPlan } from "./daemon-install-helpers.js";
|
||||
@@ -98,6 +103,95 @@ async function cleanupLegacyLaunchdService(params: {
|
||||
}
|
||||
}
|
||||
|
||||
function classifyLegacyServices(legacyServices: ExtraGatewayService[]): {
|
||||
darwinUserServices: ExtraGatewayService[];
|
||||
linuxUserServices: ExtraGatewayService[];
|
||||
failed: string[];
|
||||
} {
|
||||
const darwinUserServices: ExtraGatewayService[] = [];
|
||||
const linuxUserServices: ExtraGatewayService[] = [];
|
||||
const failed: string[] = [];
|
||||
|
||||
for (const svc of legacyServices) {
|
||||
if (svc.platform === "darwin") {
|
||||
if (svc.scope === "user") {
|
||||
darwinUserServices.push(svc);
|
||||
} else {
|
||||
failed.push(`${svc.label} (${svc.scope})`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (svc.platform === "linux") {
|
||||
if (svc.scope === "user") {
|
||||
linuxUserServices.push(svc);
|
||||
} else {
|
||||
failed.push(`${svc.label} (${svc.scope})`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
failed.push(`${svc.label} (${svc.platform})`);
|
||||
}
|
||||
|
||||
return { darwinUserServices, linuxUserServices, failed };
|
||||
}
|
||||
|
||||
async function cleanupLegacyDarwinServices(
|
||||
services: ExtraGatewayService[],
|
||||
): Promise<{ removed: string[]; failed: string[] }> {
|
||||
const removed: string[] = [];
|
||||
const failed: string[] = [];
|
||||
|
||||
for (const svc of services) {
|
||||
const plistPath = extractDetailPath(svc.detail, "plist:");
|
||||
if (!plistPath) {
|
||||
failed.push(`${svc.label} (missing plist path)`);
|
||||
continue;
|
||||
}
|
||||
const dest = await cleanupLegacyLaunchdService({
|
||||
label: svc.label,
|
||||
plistPath,
|
||||
});
|
||||
removed.push(dest ? `${svc.label} -> ${dest}` : svc.label);
|
||||
}
|
||||
|
||||
return { removed, failed };
|
||||
}
|
||||
|
||||
async function cleanupLegacyLinuxUserServices(
|
||||
services: ExtraGatewayService[],
|
||||
runtime: RuntimeEnv,
|
||||
): Promise<{ removed: string[]; failed: string[] }> {
|
||||
const removed: string[] = [];
|
||||
const failed: string[] = [];
|
||||
|
||||
try {
|
||||
const removedUnits = await uninstallLegacySystemdUnits({
|
||||
env: process.env,
|
||||
stdout: process.stdout,
|
||||
});
|
||||
const removedByLabel: Map<string, (typeof removedUnits)[number]> = new Map(
|
||||
removedUnits.map((unit) => [`${unit.name}.service`, unit] as const),
|
||||
);
|
||||
for (const svc of services) {
|
||||
const removedUnit = removedByLabel.get(svc.label);
|
||||
if (!removedUnit) {
|
||||
failed.push(`${svc.label} (legacy unit name not recognized)`);
|
||||
continue;
|
||||
}
|
||||
removed.push(`${svc.label} -> ${removedUnit.unitPath}`);
|
||||
}
|
||||
} catch (err) {
|
||||
runtime.error(`Legacy Linux gateway cleanup failed: ${String(err)}`);
|
||||
for (const svc of services) {
|
||||
failed.push(`${svc.label} (linux cleanup failed)`);
|
||||
}
|
||||
}
|
||||
|
||||
return { removed, failed };
|
||||
}
|
||||
|
||||
export async function maybeRepairGatewayServiceConfig(
|
||||
cfg: OpenClawConfig,
|
||||
mode: "local" | "remote",
|
||||
@@ -246,27 +340,21 @@ export async function maybeScanExtraGatewayServices(
|
||||
});
|
||||
if (shouldRemove) {
|
||||
const removed: string[] = [];
|
||||
const failed: string[] = [];
|
||||
for (const svc of legacyServices) {
|
||||
if (svc.platform !== "darwin") {
|
||||
failed.push(`${svc.label} (${svc.platform})`);
|
||||
continue;
|
||||
}
|
||||
if (svc.scope !== "user") {
|
||||
failed.push(`${svc.label} (${svc.scope})`);
|
||||
continue;
|
||||
}
|
||||
const plistPath = extractDetailPath(svc.detail, "plist:");
|
||||
if (!plistPath) {
|
||||
failed.push(`${svc.label} (missing plist path)`);
|
||||
continue;
|
||||
}
|
||||
const dest = await cleanupLegacyLaunchdService({
|
||||
label: svc.label,
|
||||
plistPath,
|
||||
});
|
||||
removed.push(dest ? `${svc.label} -> ${dest}` : svc.label);
|
||||
const { darwinUserServices, linuxUserServices, failed } =
|
||||
classifyLegacyServices(legacyServices);
|
||||
|
||||
if (darwinUserServices.length > 0) {
|
||||
const result = await cleanupLegacyDarwinServices(darwinUserServices);
|
||||
removed.push(...result.removed);
|
||||
failed.push(...result.failed);
|
||||
}
|
||||
|
||||
if (linuxUserServices.length > 0) {
|
||||
const result = await cleanupLegacyLinuxUserServices(linuxUserServices, runtime);
|
||||
removed.push(...result.removed);
|
||||
failed.push(...result.failed);
|
||||
}
|
||||
|
||||
if (removed.length > 0) {
|
||||
note(removed.map((line) => `- ${line}`).join("\n"), "Legacy gateway removed");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user