SNMP-Konfiguration (Host, Community, Timeout, OIDs, etc.) */ private array $config; /** * Erwartet den Teilbereich "snmp" aus der allgemeinen Konfiguration (config.php). * * @param array $snmpConfig Konfiguration für die SNMP-Abfragen */ public function __construct(array $snmpConfig) { $this->config = $snmpConfig; } /** * Liefert den aktuellen Serverstatus zurück. * * @return array Assoziatives Array mit Statuswerten (Hostname, CPU%, RAM%, etc.) * * @throws RuntimeException wenn die SNMP-Konfiguration unvollständig ist oder Abfragen fehlschlagen */ public function getServerStatus(): array { // --- 1. Konfiguration auslesen --- $host = (string)($this->config['host'] ?? '127.0.0.1'); $community = (string)($this->config['community'] ?? ''); $oids = $this->config['oids'] ?? []; $timeout = (int)($this->config['timeout'] ?? 1) * 1_000_000; // in Mikrosekunden $retries = (int)($this->config['retries'] ?? 1); // --- Prüfungen für essentielle Konfig-Werte --- if ($host === '') { throw new RuntimeException('SNMP-Konfiguration ist unvollständig (host fehlt).'); } if ($community === '') { throw new RuntimeException('SNMP-Konfiguration ist unvollständig (community fehlt).'); } if (empty($oids)) { throw new RuntimeException('SNMP-Konfiguration ist unvollständig (oids fehlen).'); } if (!function_exists('snmpget')) { throw new RuntimeException('PHP-SNMP-Erweiterung ist nicht installiert.'); } // Hilfsfunktion: SNMP-Werte bereinigen (z.B. "INTEGER: 123" -> 123) $cleanSnmpValue = fn($v) => (int)filter_var($v, FILTER_SANITIZE_NUMBER_INT); // --- 2. Uptime abfragen --- $uptimeOid = $oids['uptime'] ?? '1.3.6.1.2.1.1.3.0'; $uptimeResult = @snmpget($host, $community, $uptimeOid, $timeout, $retries); if ($uptimeResult === false) { throw new RuntimeException("SNMP Uptime GET fehlgeschlagen."); } // Uptime aus TimeTicks (Hundertstel-Sekunden) in lesbar konvertieren preg_match('/\((.*?)\)/', $uptimeResult, $matches); $uptimeTicks = (int)($matches[1] ?? 0); $uptimeSeconds = $uptimeTicks / 100; $uptimeFormatted = sprintf( '%d Tage, %02d:%02d:%02d', (int)floor($uptimeSeconds / 86400), (int)floor(($uptimeSeconds % 86400) / 3600), (int)floor(($uptimeSeconds % 3600) / 60), (int)($uptimeSeconds % 60) ); // --- 3. CPU (Durchschnitt über alle Kerne) --- $cpuTable = $oids['cpu_table'] ?? '1.3.6.1.2.1.25.3.3.1.2'; $cpuValues = @snmpwalk($host, $community, $cpuTable, $timeout, $retries); if (!is_array($cpuValues) || empty($cpuValues)) { throw new RuntimeException("SNMP CPU WALK fehlgeschlagen."); } $cpuValues = array_map($cleanSnmpValue, $cpuValues); $cpuAvg = (int)round(array_sum($cpuValues) / count($cpuValues)); // --- 4. Storage-Tabellen (RAM + Disks) --- $descrOid = $oids['storage_descr'] ?? '1.3.6.1.2.1.25.2.3.1.3'; $unitsOid = $oids['storage_units'] ?? '1.3.6.1.2.1.25.2.3.1.4'; $sizeOid = $oids['storage_size'] ?? '1.3.6.1.2.1.25.2.3.1.5'; $usedOid = $oids['storage_used'] ?? '1.3.6.1.2.1.25.2.3.1.6'; $descr = @snmpwalk($host, $community, $descrOid, $timeout, $retries); $units = @snmpwalk($host, $community, $unitsOid, $timeout, $retries); $size = @snmpwalk($host, $community, $sizeOid, $timeout, $retries); $used = @snmpwalk($host, $community, $usedOid, $timeout, $retries); if (!is_array($descr) || !is_array($units) || !is_array($size) || !is_array($used)) { throw new RuntimeException("SNMP Storage WALK fehlgeschlagen."); } // Werte bereinigen $descr = array_map(fn($v) => trim(str_ireplace('STRING:', '', $v), ' "'), $descr); $units = array_map($cleanSnmpValue, $units); $size = array_map($cleanSnmpValue, $size); $used = array_map($cleanSnmpValue, $used); // --- 5. RAM mit Fallback-Logik --- $ramPercent = null; $memTotalBytes = null; // Heuristik 1: Suche nach "Physical Memory" $ramIndex = array_search("Physical Memory", $descr); if ($ramIndex !== false) { $memTotalBytes = $units[$ramIndex] * $size[$ramIndex]; $ramUsedBytes = $units[$ramIndex] * $used[$ramIndex]; $ramPercent = ($memTotalBytes > 0) ? ($ramUsedBytes / $memTotalBytes) * 100 : 0; } // Fallback 1: Wenn nicht gefunden, suche nach ähnlichen Labels if ($ramPercent === null) { foreach ($descr as $index => $description) { $lower = strtolower($description); if (strpos($lower, 'physical') !== false || strpos($lower, 'memory') !== false || strpos($lower, 'ram') !== false) { $memTotalBytes = $units[$index] * $size[$index]; $ramUsedBytes = $units[$index] * $used[$index]; $ramPercent = ($memTotalBytes > 0) ? ($ramUsedBytes / $memTotalBytes) * 100 : 0; break; } } } // Fallback 2: Wenn immer noch nicht gefunden, nimm den kleinsten Eintrag (i.d.R. RAM) if ($ramPercent === null && count($descr) > 0) { $minIndex = 0; $minSize = PHP_INT_MAX; foreach ($size as $index => $s) { if ($s > 0 && $s < $minSize) { $minSize = $s; $minIndex = $index; } } $memTotalBytes = $units[$minIndex] * $size[$minIndex]; $ramUsedBytes = $units[$minIndex] * $used[$minIndex]; $ramPercent = ($memTotalBytes > 0) ? ($ramUsedBytes / $memTotalBytes) * 100 : 0; } // Fallback 3: Wenn gar nichts geht, Exception if ($ramPercent === null) { throw new RuntimeException("Konnte 'Physical Memory' in der SNMP Storage-Tabelle nicht finden."); } // --- 6. Disk C: / Root mit Fallback-Logik --- $diskCPercent = null; // Heuristik 1: Suche nach C:\ foreach ($descr as $index => $description) { if (str_starts_with($description, 'C:\\')) { $cTotal = $units[$index] * $size[$index]; $cUsed = $units[$index] * $used[$index]; $diskCPercent = ($cTotal > 0) ? ($cUsed / $cTotal) * 100 : 0; break; } } // Fallback 1: Suche nach "C:" oder "root" oder "/" if ($diskCPercent === null) { foreach ($descr as $index => $description) { $lower = strtolower($description); if (strpos($lower, 'c:') !== false || $lower === '/' || strpos($lower, 'root') !== false) { $cTotal = $units[$index] * $size[$index]; $cUsed = $units[$index] * $used[$index]; $diskCPercent = ($cTotal > 0) ? ($cUsed / $cTotal) * 100 : 0; break; } } } // Fallback 2: Nimm den größten Eintrag > 1GB (wahrscheinlich der Hauptdatenträger) if ($diskCPercent === null) { $maxIndex = 0; $maxSize = 0; foreach ($size as $index => $s) { $sizeGB = ($s * $units[$index]) / (1024 ** 3); if ($sizeGB > 1 && $s > $maxSize) { $maxSize = $s; $maxIndex = $index; } } if ($maxSize > 0) { $cTotal = $units[$maxIndex] * $size[$maxIndex]; $cUsed = $units[$maxIndex] * $used[$maxIndex]; $diskCPercent = ($cTotal > 0) ? ($cUsed / $cTotal) * 100 : 0; } } // Fallback 3: Wenn immer noch nichts, Exception if ($diskCPercent === null) { throw new RuntimeException("Konnte Laufwerk 'C:\\' oder Root-Partition in der SNMP Storage-Tabelle nicht finden."); } // --- 7. Status-Array zusammenbauen --- $status = [ 'hostname' => $host, 'os' => 'Windows Server', // TODO: OS dynamisch per SNMP abfragen (OID 1.3.6.1.2.1.1.1.0) 'uptime' => $uptimeFormatted, 'cpu_usage' => $cpuAvg, 'memory_usage' => (int)round($ramPercent), 'disk_usage_c' => (int)round($diskCPercent), 'last_update' => date('d.m.Y H:i:s'), ]; return $status; } }