'Postfix', 'type' => 'MTA', 'online' => $this->isRunning('postfix')], ['name' => 'Dovecot', 'type' => 'IMAP', 'online' => $this->isRunning('dovecot')], ['name' => 'Rspamd', 'type' => 'Spam', 'online' => $this->isRunning('rspamd')], ['name' => 'OpenDKIM', 'type' => 'DKIM', 'online' => $this->isRunning('opendkim')], ['name' => 'MariaDB', 'type' => 'DB', 'online' => $this->isRunning('mariadb')], ['name' => 'Redis', 'type' => 'Cache', 'online' => $this->isRunning('redis')], ['name' => 'Nginx', 'type' => 'Web', 'online' => $this->isRunning('nginx')], ['name' => 'ClamAV', 'type' => 'AV', 'online' => $this->isRunning('clamav')], ]; $servicesActive = count(array_filter($services, fn($s) => $s['online'])); $servicesTotal = count($services); [$cpu, $cpuCores, $cpuMhz] = $this->getCpu(); [$ramPercent, $ramUsed, $ramTotal] = $this->getRam(); [$load1, $load5, $load15] = $this->getLoad(); [$uptimeDays, $uptimeHours] = $this->getUptime(); [$diskUsedPercent, $diskUsedGb, $diskFreeGb, $diskTotalGb] = $this->getDisk(); return view('ui.dashboard.redesign', [ 'domainCount' => Domain::count(), 'mailboxCount' => MailUser::count(), 'servicesActive' => $servicesActive, 'servicesTotal' => $servicesTotal, 'alertCount' => 0, 'mailHostname' => gethostname() ?: 'mailserver', 'services' => $services, 'cpu' => $cpu, 'cpuCores' => $cpuCores, 'cpuMhz' => $cpuMhz, 'ramPercent' => $ramPercent, 'ramUsed' => $ramUsed, 'ramTotal' => $ramTotal, 'load1' => $load1, 'load5' => $load5, 'load15' => $load15, 'uptimeDays' => $uptimeDays, 'uptimeHours' => $uptimeHours, 'diskUsedPercent' => $diskUsedPercent, 'diskUsedGb' => $diskUsedGb, 'diskFreeGb' => $diskFreeGb, 'diskTotalGb' => $diskTotalGb, 'bounceCount' => 0, 'spamCount' => 0, 'lastBackup' => '—', 'backupSize' => '—', 'backupDuration' => '—', ]); } private function isRunning(string $service): bool { exec("systemctl is-active --quiet " . escapeshellarg($service) . " 2>/dev/null", $out, $code); return $code === 0; } private function getCpu(): array { $cores = (int) shell_exec("nproc 2>/dev/null") ?: 1; $mhz = round((float) shell_exec("awk '/^cpu MHz/{sum+=$4; n++} END{if(n)print sum/n}' /proc/cpuinfo 2>/dev/null") / 1000, 1); $s1 = $this->readStat(); usleep(400000); $s2 = $this->readStat(); // /proc/stat fields: user(0) nice(1) system(2) idle(3) iowait(4) irq(5) softirq(6) steal(7) $idle1 = $s1[3] + ($s1[4] ?? 0); $idle2 = $s2[3] + ($s2[4] ?? 0); $total1 = array_sum($s1); $total2 = array_sum($s2); $dt = $total2 - $total1; $di = $idle2 - $idle1; $cpu = $dt > 0 ? max(0, min(100, round(($dt - $di) / $dt * 100))) : 0; return [$cpu, $cores, $mhz ?: '—']; } private function readStat(): array { $raw = trim(shell_exec("head -1 /proc/stat 2>/dev/null") ?: ''); $parts = preg_split('/\s+/', $raw); array_shift($parts); // remove 'cpu' label return array_map('intval', $parts); } private function getRam(): array { $raw = shell_exec("cat /proc/meminfo 2>/dev/null") ?: ''; preg_match('/MemTotal:\s+(\d+)/', $raw, $mt); preg_match('/MemAvailable:\s+(\d+)/', $raw, $ma); $total = isset($mt[1]) ? (int)$mt[1] : 0; $avail = isset($ma[1]) ? (int)$ma[1] : 0; $used = $total - $avail; $percent = $total > 0 ? round($used / $total * 100) : 0; return [ $percent, round($used / 1048576, 1), round($total / 1048576, 1), ]; } private function getLoad(): array { $raw = trim(shell_exec("cat /proc/loadavg 2>/dev/null") ?: ''); $p = explode(' ', $raw); return [$p[0] ?? '0.00', $p[1] ?? '0.00', $p[2] ?? '0.00']; } private function getUptime(): array { $secs = (int)(float)(shell_exec("awk '{print $1}' /proc/uptime 2>/dev/null") ?: 0); return [intdiv($secs, 86400), intdiv($secs % 86400, 3600)]; } private function getDisk(): array { $raw = trim(shell_exec("df -BG / 2>/dev/null | tail -1") ?: ''); $p = preg_split('/\s+/', $raw); $total = isset($p[1]) ? (int)$p[1] : 0; $used = isset($p[2]) ? (int)$p[2] : 0; $free = isset($p[3]) ? (int)$p[3] : 0; $percent = $total > 0 ? round($used / $total * 100) : 0; return [$percent, $used, $free, $total]; } }