diff --git a/app/Console/Commands/StorageProbe.php b/app/Console/Commands/StorageProbe.php index 863bdf4..52decf2 100644 --- a/app/Console/Commands/StorageProbe.php +++ b/app/Console/Commands/StorageProbe.php @@ -18,49 +18,61 @@ class StorageProbe extends Command Setting::set('health.disk', $data); Setting::set('health.disk_updated_at', now()->toIso8601String()); + $hb = function (int $bytes): string { + $b = max(0, $bytes); + if ($b >= 1024**3) return number_format($b / 1024**3, 1).' GB'; + if ($b >= 1024**2) return number_format($b / 1024**2, 2).' MiB'; + if ($b >= 1024) return number_format($b / 1024, 0).' KiB'; + return $b.' B'; + }; + $this->info(sprintf( - 'Storage %s → total:%dGB used:%dGB free_user:%dGB free+5%%:%dGB (%%used:%d) breakdown: system=%.1fGB mails=%.1fGB backups=%.1fGB', + 'Storage %s → total:%dGB used:%dGB free_user:%dGB free+5%%:%dGB (%%used:%d) breakdown: system=%s mails=%s backups=%s', $data['mount'], $data['total_gb'], $data['used_gb'], $data['free_gb'], $data['free_plus_reserve_gb'], $data['percent_used_total'], - $data['breakdown_bytes']['system'], - $data['breakdown_bytes']['mails'], - $data['breakdown_bytes']['backup'], + $hb((int)$data['breakdown_bytes']['system']), + $hb((int)$data['breakdown_bytes']['mails']), + $hb((int)$data['breakdown_bytes']['backup']), )); +// $this->info(sprintf( +// 'Storage %s → total:%dGB used:%dGB free_user:%dGB free+5%%:%dGB (%%used:%d) breakdown: system=%.1fGB mails=%.1fGB backups=%.1fGB', +// $data['mount'], +// $data['total_gb'], +// $data['used_gb'], +// $data['free_gb'], +// $data['free_plus_reserve_gb'], +// $data['percent_used_total'], +// $data['breakdown_bytes']['system'], +// $data['breakdown_bytes']['mails'], +// $data['breakdown_bytes']['backup'], +// )); + return self::SUCCESS; } - // … oberhalb deiner probe()-Methode einfügen: private function detectMailRoot(): ?string { - // 1) Dovecot: mail_location = maildir:/var/vmail/%d/%n/Maildir + // Dovecot $ml = trim((string) @shell_exec('doveconf -n 2>/dev/null | awk -F= \'/^mail_location/ {print $2}\'')); if ($ml !== '') { - $ml = trim($ml); - // maildir:/path/to/root/%d/%n/Maildir oder mdbox:/path/…/mdbox if (preg_match('~^(?:maildir|mdbox|sdbox):([^%]+)~i', $ml, $m)) { $root = rtrim($m[1]); - // häufig endet es auf /Maildir oder /mdbox → ein Level hoch als Root nehmen foreach (['/Maildir', '/mdbox', '/sdbox'] as $suffix) { - if (str_ends_with($root, $suffix)) { - $root = dirname($root); - break; - } + if (str_ends_with($root, $suffix)) { $root = dirname($root); break; } } if (is_dir($root)) return $root; } } - - // 2) Postfix: virtual_mailbox_base = /var/vmail + // Postfix $vmb = trim((string) @shell_exec('postconf -n 2>/dev/null | awk -F= \'/^virtual_mailbox_base/ {print $2}\'')); - $vmb = $vmb !== '' ? trim($vmb) : ''; if ($vmb !== '' && is_dir($vmb)) return $vmb; - // 3) Fallbacks – nimm den ersten existierenden + // Fallbacks foreach (['/var/vmail', '/var/mail/vhosts', '/srv/mail/vhosts', '/home/vmail'] as $cand) { if (is_dir($cand)) return $cand; } @@ -70,11 +82,51 @@ class StorageProbe extends Command private function duBytesDir(string $path): int { if (!is_dir($path)) return 0; - // apparent-size zählt logisch (kleine Dateien werden nicht „weggerundet“) $out = @shell_exec('LC_ALL=C du -sb --apparent-size ' . escapeshellarg($path) . ' 2>/dev/null | cut -f1'); return max(0, (int) trim((string) $out)); } + // … oberhalb deiner probe()-Methode einfügen: +// private function detectMailRoot(): ?string +// { +// // 1) Dovecot: mail_location = maildir:/var/vmail/%d/%n/Maildir +// $ml = trim((string) @shell_exec('doveconf -n 2>/dev/null | awk -F= \'/^mail_location/ {print $2}\'')); +// if ($ml !== '') { +// $ml = trim($ml); +// // maildir:/path/to/root/%d/%n/Maildir oder mdbox:/path/…/mdbox +// if (preg_match('~^(?:maildir|mdbox|sdbox):([^%]+)~i', $ml, $m)) { +// $root = rtrim($m[1]); +// // häufig endet es auf /Maildir oder /mdbox → ein Level hoch als Root nehmen +// foreach (['/Maildir', '/mdbox', '/sdbox'] as $suffix) { +// if (str_ends_with($root, $suffix)) { +// $root = dirname($root); +// break; +// } +// } +// if (is_dir($root)) return $root; +// } +// } +// +// // 2) Postfix: virtual_mailbox_base = /var/vmail +// $vmb = trim((string) @shell_exec('postconf -n 2>/dev/null | awk -F= \'/^virtual_mailbox_base/ {print $2}\'')); +// $vmb = $vmb !== '' ? trim($vmb) : ''; +// if ($vmb !== '' && is_dir($vmb)) return $vmb; +// +// // 3) Fallbacks – nimm den ersten existierenden +// foreach (['/var/vmail', '/var/mail/vhosts', '/srv/mail/vhosts', '/home/vmail'] as $cand) { +// if (is_dir($cand)) return $cand; +// } +// return null; +// } +// +// private function duBytesDir(string $path): int +// { +// if (!is_dir($path)) return 0; +// // apparent-size zählt logisch (kleine Dateien werden nicht „weggerundet“) +// $out = @shell_exec('LC_ALL=C du -sb --apparent-size ' . escapeshellarg($path) . ' 2>/dev/null | cut -f1'); +// return max(0, (int) trim((string) $out)); +// } + protected function probe(string $target): array { // --- df: Gesamtdaten des Filesystems (inkl. Reserve) ----------------- diff --git a/app/Livewire/Ui/System/StorageCard.php b/app/Livewire/Ui/System/StorageCard.php index aa1aadd..2a6ab54 100644 --- a/app/Livewire/Ui/System/StorageCard.php +++ b/app/Livewire/Ui/System/StorageCard.php @@ -29,7 +29,7 @@ class StorageCard extends Component public ?string $measuredAt = null; protected int $segCount = 100; // Donut-Segmente - private int $legendMinBytes = 1_048_576; // 1 MiB – darunter blenden wir aus + private int $legendMinBytes = 104858; // 0,1 MiB – darunter blenden wir aus public function mount(string $target = '/'): void { @@ -202,7 +202,7 @@ class StorageCard extends Component foreach ($defs as $d) { $val = max(0, (int)($bdBytes[$d['key']] ?? 0)); // < 1 MiB NICHT anzeigen - if ($val <= 0) continue; + if ($val < $this->legendMinBytes) continue; $out[] = [ 'label' => $d['label'],