argument('target') ?: '/'; $data = $this->probe($target); Setting::set('health.disk', $data); Setting::set('health.disk_updated_at', now()->toIso8601String()); $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']['system_gb'], $data['breakdown']['mails_gb'], $data['breakdown']['backup_gb'], )); return self::SUCCESS; } protected function probe(string $target): array { // --- df: Gesamtdaten des Filesystems (inkl. Reserve) ----------------- $line = trim((string)@shell_exec('LC_ALL=C df -kP ' . escapeshellarg($target) . ' 2>/dev/null | tail -n1')); $device = $mount = ''; $totalKb = $usedKb = $availKb = 0; if ($line !== '') { $p = preg_split('/\s+/', $line); if (count($p) >= 6) { $device = $p[0]; $totalKb = (int)$p[1]; // TOTAL (inkl. Reserve) $usedKb = (int)$p[2]; // Used $availKb = (int)$p[3]; // Avail (User-sicht) $mount = $p[5]; } } $toGiB_i = static fn($kb) => (int)round(max(0, (int)$kb) / (1024 * 1024)); // ganzzahlig (UI: Gesamt/Genutzt/Frei) $toGiB_f = static fn($kb) => round(max(0, (int)$kb) / (1024 * 1024), 1); // eine Nachkommastelle (Breakdown/Legende) $totalGb = $toGiB_i($totalKb); $freeGb = $toGiB_i($availKb); // user-verfügbar $usedGb = max(0, $totalGb - $freeGb); // belegt inkl. Reserve $res5Gb = (int)round($totalGb * 0.05); // 5% von Gesamt $freePlusReserveGb = min($totalGb, $freeGb + $res5Gb); $percentUsed = $totalGb > 0 ? (int)round($usedGb * 100 / $totalGb) : 0; // --- du: reale Verbräuche bestimmter Bäume (KB) ----------------------- $duKb = function (string $path): int { if (!is_dir($path)) return 0; $kb = (int)trim((string)@shell_exec('LC_ALL=C du -sk --apparent-size ' . escapeshellarg($path) . ' 2>/dev/null | cut -f1')); return max(0, $kb); }; $kbMails = $duKb('/var/mail/vhosts'); $kbBackup = $duKb('/var/backups/mailwolt'); // „System“ = alles übrige, was nicht Mails/Backups ist (OS, App, Logs, DB-Daten, …) $gbMails = $toGiB_f($kbMails); $gbBackup = $toGiB_f($kbBackup); // system_gb aus „usedGb – (mails+backup)“, nie negativ $gbSystem = max(0, round($usedGb - ($gbMails + $gbBackup), 1)); return [ 'device' => $device ?: 'unknown', 'mount' => $mount ?: $target, 'total_gb' => $totalGb, 'used_gb' => $usedGb, // inkl. Reserve 'free_gb' => $freeGb, // User-sicht 'reserve5_gb' => $res5Gb, // Info 'free_plus_reserve_gb' => $freePlusReserveGb, // Anzeige „Frei“ 'percent_used_total' => $percentUsed, // Reale Breakdown-Werte 'breakdown' => [ 'system_gb' => $gbSystem, 'mails_gb' => $gbMails, 'backup_gb' => $gbBackup, ], ]; } } // //namespace App\Console\Commands; // //use Illuminate\Console\Command; //use App\Models\Setting; // //class StorageProbe extends Command //{ // protected $signature = 'health:probe-disk {target=/}'; // protected $description = 'Speichert Storage-Werte (inkl. Frei+5%) in settings:health.disk'; // // public function handle(): int // { // $target = $this->argument('target') ?: '/'; // $data = $this->probe($target); // // // Persistiert (DB + Redis) über dein Settings-Model // Setting::set('health.disk', $data); // Setting::set('health.disk_updated_at', now()->toIso8601String()); // // $this->info(sprintf( // 'Storage %s → total:%dGB used:%dGB free_user:%dGB free+5%%:%dGB (%%used:%d)', // $data['mount'], // $data['total_gb'], // $data['used_gb'], // $data['free_gb'], // $data['free_plus_reserve_gb'], // $data['percent_used_total'], // )); // // return self::SUCCESS; // } // // protected function probe(string $target): array // { // $line = trim((string) @shell_exec('df -kP ' . escapeshellarg($target) . ' 2>/dev/null | tail -n1')); // // $device = $mount = ''; // $totalKb = $usedKb = $availKb = 0; // // if ($line !== '') { // $p = preg_split('/\s+/', $line); // if (count($p) >= 6) { // $device = $p[0]; // $totalKb = (int) $p[1]; // TOTAL (inkl. Reserve) // $usedKb = (int) $p[2]; // Used // $availKb = (int) $p[3]; // Avail (User-sicht) // $mount = $p[5]; // } // } // // $toGiB = static fn($kb) => (int) round(max(0, (int)$kb) / (1024*1024)); // // $totalGb = $toGiB($totalKb); // $freeGb = $toGiB($availKb); // user-verfügbar // $usedGb = max(0, $totalGb - $freeGb); // belegt inkl. Reserve // $res5Gb = (int) round($totalGb * 0.05); // 5% von Gesamt // $freePlusReserveGb = min($totalGb, $freeGb + $res5Gb); // // $percentUsed = $totalGb > 0 ? (int) round($usedGb * 100 / $totalGb) : 0; // // return [ // 'device' => $device ?: 'unknown', // 'mount' => $mount ?: $target, // // 'total_gb' => $totalGb, // 'used_gb' => $usedGb, // inkl. Reserve // 'free_gb' => $freeGb, // User-sicht // 'reserve5_gb' => $res5Gb, // Info // 'free_plus_reserve_gb' => $freePlusReserveGb, // ← das willst du anzeigen // // 'percent_used_total' => $percentUsed, // fürs Donut (~15%) // 'breakdown' => [ // 'system_gb' => 5.2, // OS, App, Logs … // 'mails_gb' => 2.8, // /var/mail/vhosts // 'backup_gb' => 1.0, // /var/backups/mailwolt (oder wohin du sicherst) // ], // ]; // } //}