From 528b7df875560f572a087f32e6322e75edbc3a9c Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Mon, 4 Dec 2023 11:20:41 +0100 Subject: [PATCH] Syslog / archive - add maxfilesize option to enforce a log rotate when files exceed their limit. The combination of preserve logs and max file size help to guard the boundaries of the log storage being used, an archive action is already being performed hourly, which should be enough in normal situations (although that would be easy to change if needed). In order to make room for the new additional files per day, we add a sequence to the file, for example the first rotate of a filter log exceeding its limit named /var/log/filter/filter_20231204.log would be moved to /var/log/filter/filter_20231204.0001.log . The syslog-ng reload handles the flush to a new file, which automatically would result in a new filter_20231204.log file after rotate. --- src/opnsense/scripts/syslog/log_archive | 24 +++++++++++++++++- src/www/diag_logs_settings.php | 33 +++++++++++++++++++------ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/opnsense/scripts/syslog/log_archive b/src/opnsense/scripts/syslog/log_archive index 69e0b31da..178f01136 100755 --- a/src/opnsense/scripts/syslog/log_archive +++ b/src/opnsense/scripts/syslog/log_archive @@ -2,7 +2,7 @@ $items) { rsort($items); + /** + * Force a manual rotate when maxfilesize is specified and the newest file exceeds the specified limit. + */ + if (!empty($maxfilesize) && (filesize($items[0]) / 1024 / 1024) > $maxfilesize) { + if (isset($items[1]) && preg_match('/.*_(\d){8}\.log$/', $items[0])) { + /* Extract rotate sequence number from filename in format XXX_YYYYMMDD.log or XXX_YYYYMMDD.SEQ.log */ + $fparts = explode('_', $items[1]); + $parts = explode('.', $fparts[1]); + $seq = (count($parts) == 3 && ctype_digit($parts[1]) ? (int)$parts[1] : 0) + 1; + /* Suffix sequence number to last filename, rename and schedule a rotate (syslog-ng reload) */ + $new_filename = sprintf('%s.%04d.log', explode('.', $items[0])[0], $seq); + array_unshift($items, array_shift($items), $new_filename); + rename($items[0], $new_filename); + $rotate = true; + } + } if (count($items) > $preserve_logs) { foreach (array_slice($items, $preserve_logs) as $filename) { @unlink($filename); @@ -68,3 +86,7 @@ foreach ($relevant_logs as $log_subject => $items) { @symlink($items[0], $link); } } + +if ($rotate) { + system_syslog_start(); +} \ No newline at end of file diff --git a/src/www/diag_logs_settings.php b/src/www/diag_logs_settings.php index d63729a1a..e09286f14 100644 --- a/src/www/diag_logs_settings.php +++ b/src/www/diag_logs_settings.php @@ -60,6 +60,7 @@ function is_valid_syslog_server($target) { if ($_SERVER['REQUEST_METHOD'] === 'GET') { $pconfig = array(); $pconfig['preservelogs'] = !empty($config['syslog']['preservelogs']) ? $config['syslog']['preservelogs'] : null; + $pconfig['maxfilesize'] = !empty($config['syslog']['maxfilesize']) ? $config['syslog']['maxfilesize'] : null; $pconfig['logdefaultblock'] = empty($config['syslog']['nologdefaultblock']); $pconfig['logdefaultpass'] = empty($config['syslog']['nologdefaultpass']); $pconfig['logbogons'] = empty($config['syslog']['nologbogons']); @@ -82,15 +83,24 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { $input_errors[] = gettext("Preserve logs must be a positive integer value."); } } + if (!empty($pconfig['maxfilesize']) && (strlen($pconfig['maxfilesize']) > 0)) { + if (!is_numeric($pconfig['maxfilesize'])) { + $input_errors[] = gettext("Max file size must be a positive integer value."); + } + } + + if (count($input_errors) == 0) { if (empty($config['syslog'])) { - $config['syslog'] = array(); + $config['syslog'] = []; } - if (isset($_POST['preservelogs']) && (strlen($pconfig['preservelogs']) > 0)) { - $config['syslog']['preservelogs'] = (int)$pconfig['preservelogs']; - } elseif (isset($config['syslog']['preservelogs'])) { - unset($config['syslog']['preservelogs']); + foreach (['preservelogs', 'maxfilesize'] as $fieldname) { + if (isset($pconfig[$fieldname]) && (strlen($pconfig[$fieldname]) > 0)) { + $config['syslog'][$fieldname] = (int)$pconfig[$fieldname]; + } elseif (isset($config['syslog'][$fieldname])) { + unset($config['syslog'][$fieldname]); + } } $config['syslog']['disablelocallogging'] = !empty($pconfig['disablelocallogging']); @@ -188,11 +198,20 @@ $(document).ready(function() { - + + + + + + + +