diff --git a/app/Console/Commands/SpamAvCollectCommand.php b/app/Console/Commands/SpamAvCollectCommand.php new file mode 100644 index 0000000..ce9cab3 --- /dev/null +++ b/app/Console/Commands/SpamAvCollectCommand.php @@ -0,0 +1,45 @@ +info('Collecting Spam/AV metrics…'); + + $collect = function (): array { + $out = trim(@shell_exec('rspamc counters 2>/dev/null') ?? ''); + $ham = preg_match('/\bham\s*:\s*(\d+)/i', $out, $m1) ? (int)$m1[1] : 0; + $spam = preg_match('/\bspam\s*:\s*(\d+)/i', $out, $m2) ? (int)$m2[1] : 0; + $reject = preg_match('/\breject\s*:\s*(\d+)/i', $out, $m3) ? (int)$m3[1] : 0; + + $rspamdVer = trim(@shell_exec('rspamadm version 2>/dev/null') ?? '') ?: '–'; + $clamVer = trim(@shell_exec('clamd --version 2>/dev/null || clamscan --version 2>/dev/null') ?? '') ?: '–'; + + $sigUpdated = null; + $log = @shell_exec('grep -i "Database updated" /var/log/clamav/freshclam.log | tail -n1 2>/dev/null'); + if ($log) { $sigUpdated = trim($log); } + + return compact('ham','spam','reject','rspamdVer','clamVer','sigUpdated') + ['ts' => time()]; + }; + + $data = $collect(); + Setting::set('spamav.metrics', $data); + Cache::put('dash.spamav', $data, 60); + + $this->info(sprintf( + 'ham=%d spam=%d reject=%d | rspamd=%s | clam=%s', + $data['ham'], $data['spam'], $data['reject'], $data['rspamdVer'], $data['clamVer'] + )); + + return self::SUCCESS; + } +} diff --git a/app/Livewire/Ui/Security/SpamAvCard.php b/app/Livewire/Ui/Security/SpamAvCard.php index 8040789..577c797 100644 --- a/app/Livewire/Ui/Security/SpamAvCard.php +++ b/app/Livewire/Ui/Security/SpamAvCard.php @@ -4,6 +4,7 @@ namespace App\Livewire\Ui\Security; use Livewire\Component; use Illuminate\Support\Facades\Cache; +use App\Models\Setting; class SpamAvCard extends Component { @@ -14,30 +15,122 @@ class SpamAvCard extends Component public string $clamVer = '–'; public ?string $sigUpdated = null; - public function mount(): void { $this->load(); } - public function render() { return view('livewire.ui.security.spam-av-card'); } - public function refresh(): void { $this->load(true); } + // wie frisch müssen Zahlen mindestens sein (Sek.) + protected int $maxAge = 300; + + public function mount(): void + { + $this->load(); + } + + public function render() + { + return view('livewire.ui.security.spam-av-card'); + } + + public function refresh(): void + { + $this->load(true); + } protected function load(bool $force = false): void { - $data = Cache::remember('dash.spamav', $force ? 1 : 60, function () { - $out = trim(@shell_exec('rspamc counters 2>/dev/null') ?? ''); - // very rough counters (adapt to your setup) - $ham = preg_match('/ham:\s*(\d+)/i', $out, $m1) ? (int)$m1[1] : 0; - $spam = preg_match('/spam:\s*(\d+)/i', $out, $m2) ? (int)$m2[1] : 0; - $reject = preg_match('/reject:\s*(\d+)/i', $out, $m3) ? (int)$m3[1] : 0; + // 1) Versuche erst aus Settings (DB/Redis), optional mit Cache-Shortcuts + $data = $force ? null : Cache::get('dash.spamav'); - $rspamdVer = trim(@shell_exec('rspamadm version 2>/dev/null') ?? '') ?: '–'; - $clamVer = trim(@shell_exec('clamd --version 2>/dev/null || clamscan --version 2>/dev/null') ?? '') ?: '–'; + if (!$data) { + $data = Setting::get('spamav.metrics'); + } - // last signatures update (freshclam log) - $sigUpdated = null; - $log = @shell_exec('grep -i "Database updated" /var/log/clamav/freshclam.log | tail -n1 2>/dev/null'); - if ($log) $sigUpdated = trim($log); + // 2) Wenn keine Daten oder zu alt ⇒ neu sammeln + $stale = !is_array($data) || (time() - (int)($data['ts'] ?? 0) > $this->maxAge); + if ($force || $stale) { + $data = $this->collectMetrics(); + // Persistenz: Settings (DB→Redis) + UI-Cache (kurz) + Setting::set('spamav.metrics', $data); + Cache::put('dash.spamav', $data, 60); + } - return compact('ham','spam','reject','rspamdVer','clamVer','sigUpdated'); - }); + // 3) Auf Properties mappen + $this->ham = (int)($data['ham'] ?? 0); + $this->spam = (int)($data['spam'] ?? 0); + $this->reject = (int)($data['reject'] ?? 0); + $this->rspamdVer = (string)($data['rspamdVer'] ?? '–'); + $this->clamVer = (string)($data['clamVer'] ?? '–'); + $this->sigUpdated = $data['sigUpdated'] ?? null; + } - foreach ($data as $k => $v) $this->$k = $v; + /** Sammelt live von rspamd/clamav – robust und schnell */ + protected function collectMetrics(): array + { + // rspamd counters + $out = trim(@shell_exec('rspamc counters 2>/dev/null') ?? ''); + $ham = preg_match('/\bham\s*:\s*(\d+)/i', $out, $m1) ? (int)$m1[1] : 0; + $spam = preg_match('/\bspam\s*:\s*(\d+)/i', $out, $m2) ? (int)$m2[1] : 0; + $reject = preg_match('/\breject\s*:\s*(\d+)/i', $out, $m3) ? (int)$m3[1] : 0; + + // Versionen + $rspamdVer = trim(@shell_exec('rspamadm version 2>/dev/null') ?? '') ?: '–'; + $clamVer = trim(@shell_exec('clamd --version 2>/dev/null || clamscan --version 2>/dev/null') ?? '') ?: '–'; + + // Letztes Signatur-Update aus freshclam.log + $sigUpdated = null; + $log = @shell_exec('grep -i "Database updated" /var/log/clamav/freshclam.log | tail -n1 2>/dev/null'); + if ($log) { + $sigUpdated = trim($log); + } + + return [ + 'ts' => time(), + 'ham' => $ham, + 'spam' => $spam, + 'reject' => $reject, + 'rspamdVer' => $rspamdVer, + 'clamVer' => $clamVer, + 'sigUpdated' => $sigUpdated, + ]; } } + +// +//namespace App\Livewire\Ui\Security; +// +//use Livewire\Component; +//use Illuminate\Support\Facades\Cache; +// +//class SpamAvCard extends Component +//{ +// public int $ham = 0; +// public int $spam = 0; +// public int $reject = 0; +// public string $rspamdVer = '–'; +// public string $clamVer = '–'; +// public ?string $sigUpdated = null; +// +// public function mount(): void { $this->load(); } +// public function render() { return view('livewire.ui.security.spam-av-card'); } +// public function refresh(): void { $this->load(true); } +// +// protected function load(bool $force = false): void +// { +// $data = Cache::remember('dash.spamav', $force ? 1 : 60, function () { +// $out = trim(@shell_exec('rspamc counters 2>/dev/null') ?? ''); +// // very rough counters (adapt to your setup) +// $ham = preg_match('/ham:\s*(\d+)/i', $out, $m1) ? (int)$m1[1] : 0; +// $spam = preg_match('/spam:\s*(\d+)/i', $out, $m2) ? (int)$m2[1] : 0; +// $reject = preg_match('/reject:\s*(\d+)/i', $out, $m3) ? (int)$m3[1] : 0; +// +// $rspamdVer = trim(@shell_exec('rspamadm version 2>/dev/null') ?? '') ?: '–'; +// $clamVer = trim(@shell_exec('clamd --version 2>/dev/null || clamscan --version 2>/dev/null') ?? '') ?: '–'; +// +// // last signatures update (freshclam log) +// $sigUpdated = null; +// $log = @shell_exec('grep -i "Database updated" /var/log/clamav/freshclam.log | tail -n1 2>/dev/null'); +// if ($log) $sigUpdated = trim($log); +// +// return compact('ham','spam','reject','rspamdVer','clamVer','sigUpdated'); +// }); +// +// foreach ($data as $k => $v) $this->$k = $v; +// } +//} diff --git a/app/Livewire/Ui/System/UpdateCard.php b/app/Livewire/Ui/System/UpdateCard.php index 24e0df1..be1d9a0 100644 --- a/app/Livewire/Ui/System/UpdateCard.php +++ b/app/Livewire/Ui/System/UpdateCard.php @@ -108,6 +108,9 @@ class UpdateCard extends Component if ($this->rc === 0 && !$this->postActionsDone) { // Dienste neu starten (asynchron) @shell_exec('nohup php /var/www/mailwolt/artisan mailwolt:restart-services >/dev/null 2>&1 &'); + @shell_exec('nohup php /var/www/mailwolt/artisan settings:sync >/dev/null 2>&1 &'); + @shell_exec('nohup php /var/www/mailwolt/artisan spamav:collect >/dev/null 2>&1 &'); + $this->postActionsDone = true; $ver = $this->displayCurrent ?? 'aktuelle Version'; diff --git a/routes/console.php b/routes/console.php index eda6f4d..d49dff7 100644 --- a/routes/console.php +++ b/routes/console.php @@ -9,8 +9,8 @@ Artisan::command('inspire', function () { $this->comment(Inspiring::quote()); })->purpose('Display an inspiring quote'); -Schedule::job(RunHealthChecks::class)->everyMinute()->withoutOverlapping(); -//Schedule::command('woltguard:collect-services')->everyMinute(); +Schedule::job(RunHealthChecks::class)->everyFiveMinutes()->withoutOverlapping(); +Schedule::command('spamav:collect')->everyFiveMinutes()->withoutOverlapping(); //Schedule::command('mailwolt:check-updates')->dailyAt('04:10'); Schedule::command('mailwolt:check-updates')->everytwoMinutes();