r004: Auto-Restart + WebGUI-Restart-Button + dynamische Version

- Auto-Restart: Binary erkennt Update auf Platte (mtime/size) → rc.mua restart
- WebGUI: 'MUA neu starten'-Button (POST /restart über Config-Server)
- POST-INSTALL/UPDATE: Service wird nach Installation/Update automatisch neu gestartet
- WebGUI: Version dynamisch aus /health (kein hartkodiertes rNNN)
- MUA_VERSION in helpers.ts auf r004
- .txz neu gepackt, SHA256 aktualisiert
This commit is contained in:
Mikei386
2026-08-18 11:40:17 +02:00
parent b05cc89a3d
commit aec6ba76ce
9 changed files with 122 additions and 14 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ import { createConnection, type Socket } from "net";
// ── Konstanten ──────────────────────────────────────────────────────────
export const MUA_SERVER_NAME = "mua";
export const MUA_VERSION = "2026.08.18.r003";
export const MUA_VERSION = "2026.08.18.r004";
export const MUA_PROTOCOL_VERSION = "2025-03-26";
export const PHP_HELPER = "/usr/local/bin/unraid-docker-mcp-helper.php";
+61 -1
View File
@@ -21,6 +21,8 @@ import {
import { TOOLS, toolByName } from "./tools";
import { checkAuth, isToolEnabled, getApiKey, getEnabledTools, setApiKey, setEnabledTools } from "./auth";
import { randomBytes } from "node:crypto";
import { spawn } from "node:child_process";
import { statSync } from "node:fs";
const PORT = Number(process.env["MUA_PORT"] ?? 3002);
const HOST = process.env["MUA_HOST"] ?? "0.0.0.0";
@@ -312,10 +314,25 @@ try {
const path = url.pathname;
const method = req.method;
if (path !== "/config") {
if (path !== "/config" && path !== "/restart") {
return Response.json({ error: "Not found" }, { status: 404 });
}
// POST /restart: Service neu starten (für WebGUI-Button)
if (path === "/restart" && method === "POST") {
const rcScript = process.env["MUA_RC_SCRIPT"] ?? "/etc/rc.d/rc.mua";
try {
const child = spawn(rcScript, ["restart"], {
detached: true,
stdio: "ignore",
});
child.unref();
return Response.json({ ok: true, message: "Restart initiated" });
} catch (e) {
return Response.json({ error: String(e) }, { status: 500 });
}
}
// GET: Config lesen
if (method === "GET") {
return Response.json({
@@ -368,6 +385,49 @@ console.log(
(configServer ? ` + 127.0.0.1:${CONFIG_PORT} (config)` : " (config: NICHT VERFÜGBAR)"),
);
// ── Auto-Restart bei Binary-Update ──────────────────────────────────────
// Beim Plugin-Update wird das Binary auf Platte ersetzt, aber der laufende
// Prozess hält das alte Binary im Speicher (Linux-Verhalten). Wir erkennen
// den Change (mtime + size) und starten den Service automatisch neu.
const BINARY_PATH = process.env["MUA_BINARY"] ?? "/usr/local/bin/mua";
const RC_SCRIPT = process.env["MUA_RC_SCRIPT"] ?? "/etc/rc.d/rc.mua";
let binarySnapshot: { mtimeMs: number; size: number } | null = null;
try {
const st = statSync(BINARY_PATH);
binarySnapshot = { mtimeMs: st.mtimeMs, size: st.size };
} catch {
// Binary-Pfad nicht lesbar (z.B. lokaler Test) — Auto-Restart deaktiviert
}
function checkBinaryUpdate() {
if (!binarySnapshot) return;
try {
const st = statSync(BINARY_PATH);
if (st.mtimeMs !== binarySnapshot.mtimeMs || st.size !== binarySnapshot.size) {
console.log(
`[MUA] Binary-Update erkannt (${BINARY_PATH} geändert). ` +
`Starte Service neu: ${RC_SCRIPT} restart`,
);
// rc.mua restart detached ausführen, dann sauber beenden
const child = spawn(RC_SCRIPT, ["restart"], {
detached: true,
stdio: "ignore",
});
child.unref();
// Kurze Pause, damit der Log-Flush durchkommt
setTimeout(() => process.exit(0), 500);
}
} catch {
// Binary temporär nicht lesbar — ignorieren
}
}
const updateCheckInterval = setInterval(
checkBinaryUpdate,
Number(process.env["MUA_UPDATE_CHECK_INTERVAL"] ?? 30_000),
);
updateCheckInterval.unref();
// Graceful shutdown
process.on("SIGTERM", () => {
console.log("[MUA] SIGTERM received, shutting down");