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:
BIN
Binary file not shown.
+1
-1
@@ -10,7 +10,7 @@
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 0); // Fehler werden als JSON-RPC-Error zurückgegeben, nicht als HTML
|
||||
|
||||
const MUA_VERSION = '2026.08.18.r003';
|
||||
const MUA_VERSION = '2026.08.18.r004';
|
||||
const MUA_SERVER_NAME = 'mua';
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ const MUA_PORT = 3002;
|
||||
const MUA_BIND = '0.0.0.0';
|
||||
const MUA_SESSION_TTL = 3600; // Sekunden
|
||||
const MUA_SERVER_NAME = 'mua';
|
||||
const MUA_VERSION = '2026.08.18.r003';
|
||||
const MUA_VERSION = '2026.08.18.r004';
|
||||
|
||||
// ── Session-Management (in-memory) ───────────────────────────────────────
|
||||
$sessions = []; // session_id => ['created' => time, 'initialized' => bool]
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mua",
|
||||
"version": "2026.08.18.r003",
|
||||
"version": "2026.08.18.r004",
|
||||
"description": "Mikes Unraid Agent - MCP over HTTP (Streamable HTTP) for Unraid",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
|
||||
+20
-7
@@ -2,13 +2,13 @@
|
||||
<!DOCTYPE PLUGIN [
|
||||
<!ENTITY name "mua">
|
||||
<!ENTITY author "Michael">
|
||||
<!ENTITY version "2026.08.18.r003">
|
||||
<!ENTITY version "2026.08.18.r004">
|
||||
<!ENTITY launch "Settings/MUA">
|
||||
<!ENTITY pluginURL "http://192.168.1.2:4000/michael/MUA-Mikes-Unraid-Agent/raw/branch/main/plugin/mua.plg">
|
||||
<!ENTITY pluginLOC "/boot/config/plugins/&name;">
|
||||
<!ENTITY emhttpLOC "/usr/local/emhttp/plugins/&name;">
|
||||
<!ENTITY txzURL "http://192.168.1.2:4000/michael/MUA-Mikes-Unraid-Agent/raw/branch/main/dist/mua-2026.08.18.r003-x86_64-1.txz">
|
||||
<!ENTITY txzSHA256 "ee6227a5367e57508e7408111041102a85ce260386730860c26dc6284ae5f03e">
|
||||
<!ENTITY txzURL "http://192.168.1.2:4000/michael/MUA-Mikes-Unraid-Agent/raw/branch/main/dist/mua-2026.08.18.r004-x86_64-1.txz">
|
||||
<!ENTITY txzSHA256 "0c56cc645de4f312f7d6ded3872734b1ba8607ba993c6ec1519f3768435eca2f">
|
||||
]>
|
||||
|
||||
<PLUGIN name="&name;"
|
||||
@@ -23,7 +23,12 @@
|
||||
>
|
||||
|
||||
<CHANGES>
|
||||
### 2026.08.18.r003
|
||||
### 2026.08.18.r004
|
||||
- Auto-Restart: Binary erkennt Update auf Platte (mtime/size) und startet den Service automatisch neu.
|
||||
- WebGUI: „MUA neu starten"-Button (manueller Restart über Config-Server).
|
||||
- POST-INSTALL/UPDATE: Service wird nach Installation/Update automatisch neu gestartet.
|
||||
- WebGUI: Version wird dynamisch aus /health gelesen (kein hartkodiertes rNNN).
|
||||
### 2026.08.18.r002
|
||||
- API-Key-Authentifizierung (Bearer-Token) für den MCP-HTTP-Endpunkt (Port 3002). /health bleibt offen.
|
||||
- Einstellungs-Maske im WebGUI-Tab: API-Key generieren + Tools per Checkbox aktivieren/deaktivieren.
|
||||
- Config-Server auf 127.0.0.1:3013 (nur localhost) für WebGUI-Integration.
|
||||
@@ -70,23 +75,31 @@ Das .txz enthält:
|
||||
install/doinst.sh (läuft nach Installation)
|
||||
===========================================
|
||||
-->
|
||||
<FILE Name="mua-2026.08.18.r003-x86_64-1.txz" Run="upgradepkg --install-new" Mode="755" Min="7.0.0">
|
||||
<FILE Name="mua-2026.08.18.r004-x86_64-1.txz" Run="upgradepkg --install-new" Mode="755" Min="7.0.0">
|
||||
<URL>&txzURL;</URL>
|
||||
<SHA256>&txzSHA256;</SHA256>
|
||||
</FILE>
|
||||
|
||||
<!--
|
||||
===========================================
|
||||
POST-INSTALL: Health-Check
|
||||
POST-INSTALL: Service neu starten + Health-Check
|
||||
===========================================
|
||||
Läuft nach Installation UND nach Update.
|
||||
`restart` stoppt den Service (falls er läuft) und startet ihn neu —
|
||||
funktioniert sowohl bei Erstinstallation als auch bei Update.
|
||||
===========================================
|
||||
-->
|
||||
<FILE Run="/bin/bash">
|
||||
<INLINE>
|
||||
set +e
|
||||
|
||||
echo ""
|
||||
echo " Starte MUA-Service neu..."
|
||||
/etc/rc.d/rc.mua restart 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo " Führe Health-Check aus..."
|
||||
sleep 2
|
||||
sleep 3
|
||||
if curl -sf "http://127.0.0.1:3002/health" > /dev/null 2>&1; then
|
||||
echo ""
|
||||
echo " Health-Check: OK"
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "mua",
|
||||
"author": "Michael",
|
||||
"version": "2026.08.18.r003",
|
||||
"version": "2026.08.18.r004",
|
||||
"minver": "7.0.0",
|
||||
"pluginDirectory": "/usr/local/emhttp/plugins/mua",
|
||||
"configDirectory": "/boot/config/plugins/mua",
|
||||
|
||||
+36
-1
@@ -49,6 +49,13 @@ $health_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
$health_ok = ($health_code === 200);
|
||||
|
||||
// Version aus /health lesen (dynamisch, kein hartkodiertes rNNN)
|
||||
$running_version = '';
|
||||
if ($health_ok && $health !== false) {
|
||||
$h = json_decode($health, true);
|
||||
$running_version = $h['version'] ?? '';
|
||||
}
|
||||
|
||||
// ── Config vom Config-Server laden (Port 3003) ──────────────────────────
|
||||
$config = null;
|
||||
$ch = curl_init('http://127.0.0.1:' . $config_port . '/config');
|
||||
@@ -91,6 +98,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$payload['enabledTools'] = $selected;
|
||||
}
|
||||
|
||||
// C) Service neu starten
|
||||
if (isset($_POST['action']) && $_POST['action'] === 'restart') {
|
||||
$ch = curl_init('http://127.0.0.1:' . $config_port . '/restart');
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 5,
|
||||
CURLOPT_CONNECTTIMEOUT => 3,
|
||||
CURLOPT_POST => true,
|
||||
]);
|
||||
$resp_raw = curl_exec($ch);
|
||||
$resp_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($resp_code === 200) {
|
||||
$flash_msg = 'MUA wird neu gestartet (Service restart).';
|
||||
$flash_type = 'ok';
|
||||
} else {
|
||||
$flash_msg = 'Fehler beim Neustart (HTTP ' . $resp_code . ')';
|
||||
$flash_type = 'err';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($payload)) {
|
||||
$ch = curl_init('http://127.0.0.1:' . $config_port . '/config');
|
||||
curl_setopt_array($ch, [
|
||||
@@ -248,7 +276,7 @@ $tool_groups = [
|
||||
<h2>Details</h2>
|
||||
<table>
|
||||
<tr><th>Plugin</th><td>MUA (Mikes Unraid Agent)</td></tr>
|
||||
<tr><th>Version</th><td>2026.08.18.r003</td></tr>
|
||||
<tr><th>Version</th><td><?php echo $running_version ? htmlspecialchars($running_version) : '—'; ?></td></tr>
|
||||
<tr><th>Runtime</th><td>TypeScript (Bun Runtime, kompiliertes Binary)</td></tr>
|
||||
<tr><th>Binary</th><td><code><?= $binary ?></code> <?= $binary_exists ? '✅' : '❌ fehlt' ?></td></tr>
|
||||
<tr><th>Port (MCP)</th><td><?= $port ?></td></tr>
|
||||
@@ -268,3 +296,10 @@ $tool_groups = [
|
||||
<tr><td>Status</td><td><code>/etc/rc.d/rc.mua status</code></td></tr>
|
||||
<tr><td>Logs</td><td><code>tail -f /var/log/plugins/mua.log</code></td></tr>
|
||||
</table>
|
||||
|
||||
<h2>Service neu starten</h2>
|
||||
<p>Startet den MCP-Service neu (z. B. nach einem Plugin-Update, wenn sich das Binary geändert hat).</p>
|
||||
<form method="post" onsubmit="return confirm('MUA-Service neu starten?');">
|
||||
<input type="hidden" name="action" value="restart">
|
||||
<button type="submit" class="btn btn-primary">🔄 MUA neu starten</button>
|
||||
</form>
|
||||
|
||||
+1
-1
@@ -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
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user