parent
59c495af84
commit
3e1749d547
|
|
@ -18,49 +18,61 @@ class StorageProbe extends Command
|
||||||
Setting::set('health.disk', $data);
|
Setting::set('health.disk', $data);
|
||||||
Setting::set('health.disk_updated_at', now()->toIso8601String());
|
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(
|
$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['mount'],
|
||||||
$data['total_gb'],
|
$data['total_gb'],
|
||||||
$data['used_gb'],
|
$data['used_gb'],
|
||||||
$data['free_gb'],
|
$data['free_gb'],
|
||||||
$data['free_plus_reserve_gb'],
|
$data['free_plus_reserve_gb'],
|
||||||
$data['percent_used_total'],
|
$data['percent_used_total'],
|
||||||
$data['breakdown_bytes']['system'],
|
$hb((int)$data['breakdown_bytes']['system']),
|
||||||
$data['breakdown_bytes']['mails'],
|
$hb((int)$data['breakdown_bytes']['mails']),
|
||||||
$data['breakdown_bytes']['backup'],
|
$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;
|
return self::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// … oberhalb deiner probe()-Methode einfügen:
|
|
||||||
private function detectMailRoot(): ?string
|
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}\''));
|
$ml = trim((string) @shell_exec('doveconf -n 2>/dev/null | awk -F= \'/^mail_location/ {print $2}\''));
|
||||||
if ($ml !== '') {
|
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)) {
|
if (preg_match('~^(?:maildir|mdbox|sdbox):([^%]+)~i', $ml, $m)) {
|
||||||
$root = rtrim($m[1]);
|
$root = rtrim($m[1]);
|
||||||
// häufig endet es auf /Maildir oder /mdbox → ein Level hoch als Root nehmen
|
|
||||||
foreach (['/Maildir', '/mdbox', '/sdbox'] as $suffix) {
|
foreach (['/Maildir', '/mdbox', '/sdbox'] as $suffix) {
|
||||||
if (str_ends_with($root, $suffix)) {
|
if (str_ends_with($root, $suffix)) { $root = dirname($root); break; }
|
||||||
$root = dirname($root);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (is_dir($root)) return $root;
|
if (is_dir($root)) return $root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Postfix
|
||||||
// 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 = 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;
|
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) {
|
foreach (['/var/vmail', '/var/mail/vhosts', '/srv/mail/vhosts', '/home/vmail'] as $cand) {
|
||||||
if (is_dir($cand)) return $cand;
|
if (is_dir($cand)) return $cand;
|
||||||
}
|
}
|
||||||
|
|
@ -70,11 +82,51 @@ class StorageProbe extends Command
|
||||||
private function duBytesDir(string $path): int
|
private function duBytesDir(string $path): int
|
||||||
{
|
{
|
||||||
if (!is_dir($path)) return 0;
|
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');
|
$out = @shell_exec('LC_ALL=C du -sb --apparent-size ' . escapeshellarg($path) . ' 2>/dev/null | cut -f1');
|
||||||
return max(0, (int) trim((string) $out));
|
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
|
protected function probe(string $target): array
|
||||||
{
|
{
|
||||||
// --- df: Gesamtdaten des Filesystems (inkl. Reserve) -----------------
|
// --- df: Gesamtdaten des Filesystems (inkl. Reserve) -----------------
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class StorageCard extends Component
|
||||||
public ?string $measuredAt = null;
|
public ?string $measuredAt = null;
|
||||||
|
|
||||||
protected int $segCount = 100; // Donut-Segmente
|
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
|
public function mount(string $target = '/'): void
|
||||||
{
|
{
|
||||||
|
|
@ -202,7 +202,7 @@ class StorageCard extends Component
|
||||||
foreach ($defs as $d) {
|
foreach ($defs as $d) {
|
||||||
$val = max(0, (int)($bdBytes[$d['key']] ?? 0));
|
$val = max(0, (int)($bdBytes[$d['key']] ?? 0));
|
||||||
// < 1 MiB NICHT anzeigen
|
// < 1 MiB NICHT anzeigen
|
||||||
if ($val <= 0) continue;
|
if ($val < $this->legendMinBytes) continue;
|
||||||
|
|
||||||
$out[] = [
|
$out[] = [
|
||||||
'label' => $d['label'],
|
'label' => $d['label'],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue