'Datenbank sichern', 'maildir' => 'Maildir kopieren', 'app' => 'App sichern', 'configs' => 'Configs sichern', 'archive' => 'Archiv erstellen', 'compress' => 'Komprimieren', 'retention' => 'Aufräumen', 'finish' => 'Abschluss', ]; protected string $statusFile = '/var/lib/mailwolt/backup.status'; public function mount(): void { $this->load(true); } public function render() { return view('livewire.ui.system.backup-status-card'); } public function refresh(): void { $this->load(true); } public function runNow(): void { @shell_exec('nohup sudo -n /usr/local/sbin/mailwolt-backup >/dev/null 2>&1 &'); // Sofort in "running" gehen – Poll übernimmt dann $this->state = 'running'; $this->step = 'mysqldump'; } public function load(bool $force = false): void { $raw = $this->readStatus(); $this->state = $raw['state'] ?? 'idle'; $this->step = $raw['step'] ?? ''; // Datum/Zeit hübsch if (!empty($raw['time'])) { $this->lastAt = $this->fmtTime($raw['time']); } else { $this->lastAt = null; } // Größe/Dauer hübsch $bytes = isset($raw['size_bytes']) ? (int)$raw['size_bytes'] : null; $secs = isset($raw['dur_seconds']) ? (int)$raw['dur_seconds'] : null; $this->lastSize = $bytes !== null ? $this->humanBytes($bytes) : null; $this->lastDuration = $secs !== null ? $this->humanDuration($secs) : null; $this->ok = isset($raw['ok']) ? ((string)$raw['ok'] === '1') : null; } protected function readStatus(): array { if (!is_file($this->statusFile)) return []; $out = []; foreach (@file($this->statusFile, FILE_IGNORE_NEW_LINES) ?: [] as $ln) { if (!str_contains($ln, '=')) continue; [$k, $v] = array_map('trim', explode('=', $ln, 2)); $out[$k] = $v; } // Backward compatibility (alte Keys) if (isset($out['size']) && !isset($out['size_bytes'])) { $out['size_bytes'] = (int)$out['size']; } if (isset($out['dur']) && !isset($out['dur_seconds'])) { $out['dur_seconds'] = (int)$out['dur']; } return $out; } protected function fmtTime(string $iso): string { try { $tz = config('app.timezone', 'UTC'); // ISO aus Script ist idealerweise UTC (Z) $dt = CarbonImmutable::parse($iso)->timezone($tz); // z.B. 27.10.2025, 16:48:02 (CET) return $dt->isoFormat('L, LTS') . ' ' . $dt->format('T'); } catch (\Throwable) { return $iso; } } protected function humanBytes(int $bytes): string { $units = ['B', 'KB', 'MB', 'GB', 'TB']; $i = 0; while ($bytes >= 1024 && $i < count($units) - 1) { $bytes /= 1024; $i++; } return number_format($bytes, $i === 0 ? 0 : 1, ',', '.') . ' ' . $units[$i]; } protected function humanDuration(int $secs): string { if ($secs < 60) return $secs . ' s'; $m = intdiv($secs, 60); $s = $secs % 60; if ($m < 60) return sprintf('%d min %02d s', $m, $s); $h = intdiv($m, 60); $m = $m % 60; return sprintf('%d h %02d min', $h, $m); } } // //namespace App\Livewire\Ui\System; // //use Livewire\Component; // //class BackupStatusCard extends Component //{ // public ?string $lastAt = null; // public ?string $lastSize = null; // public ?string $lastDuration = null; // public ?bool $ok = null; // // public function mount(): void { $this->load(); } // public function render() { return view('livewire.ui.system.backup-status-card'); } // public function refresh(): void { $this->load(true); } // // public function runNow(): void // { // @shell_exec('nohup sudo -n /usr/local/sbin/mailwolt-backup >/dev/null 2>&1 &'); //// $this->dispatch('toast', type:'info', title:'Backup gestartet'); // } // // protected function load(bool $force=false): void // { // // Example: parse a tiny status file your backup script writes. // $f = '/var/lib/mailwolt/backup.status'; // if (is_file($f)) { // $lines = @file($f, FILE_IGNORE_NEW_LINES) ?: []; // foreach ($lines as $ln) { // if (str_starts_with($ln,'time=')) $this->lastAt = substr($ln,5); // if (str_starts_with($ln,'size=')) $this->lastSize = substr($ln,5); // if (str_starts_with($ln,'dur=')) $this->lastDuration = substr($ln,4); // if (str_starts_with($ln,'ok=')) $this->ok = (substr($ln,3) === '1'); // } // } // } //}