diff --git a/htdocs/admin/syslog.php b/htdocs/admin/syslog.php index d850e7eeb11..e434f669f45 100644 --- a/htdocs/admin/syslog.php +++ b/htdocs/admin/syslog.php @@ -146,6 +146,16 @@ if ($action == 'setlevel') dol_syslog("admin/syslog: level ".$level); if (! $res > 0) $error++; + + if (! $error) + { + $file_saves = GETPOST("file_saves"); + $res = dolibarr_set_const($db,"SYSLOG_FILE_SAVES",$file_saves,'chaine',0,'',0); + dol_syslog("admin/syslog: file saves ".$file_saves); + + if (! $res > 0) $error++; + } + if (! $error) { setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); @@ -284,6 +294,13 @@ print ''; print ''; print ''; + +if(! empty($conf->loghandlers['mod_syslog_file']) && ! empty($conf->cron->enabled)) { + print ''.$langs->trans("SyslogFileNumberOfSaves").''; + print ''; + print ' ('.$langs->trans('ConfigureCleaningCronjobToSetFrequencyOfSaves').')'; +} + print ''; print "\n"; diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index 37ccea748f1..e60070f1179 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -93,7 +93,7 @@ class Utils // Define files log if ($dolibarr_main_data_root) { - $filesarray=dol_dir_list($dolibarr_main_data_root, "files", 0, '.*\.log[\.0-9]*$', 'install\.lock$', 'name', SORT_ASC, 0, 0, '', 1); + $filesarray=dol_dir_list($dolibarr_main_data_root, "files", 0, '.*\.log[\.0-9]*(\.gz)?$', 'install\.lock$', 'name', SORT_ASC, 0, 0, '', 1); } $filelog=''; @@ -668,4 +668,112 @@ class Utils return -1; } -} + + /** + * This saves syslog files and compresses older ones + * Used from cronjob + * + * @return int 0 if OK, < 0 if KO + */ + function compressSyslogs() { + global $conf; + + if(empty($conf->loghandlers['mod_syslog_file'])) { // File Syslog disabled + return 0; + } + + if(! function_exists('gzopen')) { + return -1; + } + + dol_include_once('/core/lib/files.lib.php'); + + $nbSaves = ! empty($conf->global->SYSLOG_FILE_SAVES) ? intval($conf->global->SYSLOG_FILE_SAVES) : 14; + + if(empty($conf->global->SYSLOG_FILE)) { + $mainlogdir = DOL_DATA_ROOT; + $mainlog = 'dolibarr.log'; + } else { + $mainlogfull = str_replace('DOL_DATA_ROOT', DOL_DATA_ROOT, $conf->global->SYSLOG_FILE); + $mainlogdir = dirname($mainlogfull); + $mainlog = basename($mainlogfull); + } + + $tabfiles = dol_dir_list(DOL_DATA_ROOT, 'files', 0, '^(dolibarr_.+|odt2pdf)\.log$'); // Also handle other log files like dolibarr_install.log + $tabfiles[] = array('name' => $mainlog, 'path' => $mainlogdir); + + foreach($tabfiles as $file) { + + $logname = $file['name']; + $logpath = $file['path']; + + // Handle already compressed files + + $filter = '^'.preg_quote($logname, '/').'\.([0-9]+)\.gz$'; + + $gzfilestmp = dol_dir_list($logpath, 'files', 0, $filter); + $gzfiles = array(); + + foreach($gzfilestmp as $gzfile) { + $tabmatches = array(); + preg_match('/'.$filter.'/i', $gzfile['name'], $tabmatches); + + $numsave = intval($tabmatches[1]); + + $gzfiles[$numsave] = $gzfile; + } + + krsort($gzfiles, SORT_NUMERIC); + + foreach($gzfiles as $numsave => $dummy) { + if(dol_is_file($logpath.'/'.$logname.'.'.($numsave+1).'.gz')) { + return -2; + } + + if($numsave >= $nbSaves) { + dol_delete_file($logpath.'/'.$logname.'.'.$numsave.'.gz'); + } else { + dol_move($logpath.'/'.$logname.'.'.$numsave.'.gz', $logpath.'/'.$logname.'.'.($numsave+1).'.gz', 0, 1, 0, 0); + } + } + + // Compress last save + + if(dol_is_file($logpath.'/'.$logname.'.1')) { + if($nbSaves > 1) { + $gzfilehandle = gzopen($logpath.'/'.$logname.'.2.gz', 'wb9'); + + if(empty($gzfilehandle)) { + return -3; + } + + $sourcehandle = fopen($logpath.'/'.$logname.'.1', 'r'); + + if(empty($sourcehandle)) { + return -4; + } + + while(! feof($sourcehandle)) { + gzwrite($gzfilehandle, fread($sourcehandle, 512 * 1024)); // Read 512 kB at a time + } + + fclose($sourcehandle); + gzclose($gzfilehandle); + } else { + dol_delete_file($logpath.'/'.$logname.'.1'); + } + } + + // Compress current file et recreate it + + if(dol_is_file($logpath.'/'.$logname)) { + if(dol_move($logpath.'/'.$logname, $logpath.'/'.$logname.'.1', 0, 1, 0, 0)) { + $newlog = fopen($logpath.'/'.$logname, 'a+'); + fclose($newlog); + } + } + } + + return 0; + } +} \ No newline at end of file diff --git a/htdocs/core/modules/modSyslog.class.php b/htdocs/core/modules/modSyslog.class.php index 97c7b71ae21..b3e83f90ca2 100644 --- a/htdocs/core/modules/modSyslog.class.php +++ b/htdocs/core/modules/modSyslog.class.php @@ -79,5 +79,10 @@ class modSyslog extends DolibarrModules // Permissions $this->rights = array(); $this->rights_class = 'syslog'; + + // Cronjobs + $this->cronjobs = array( + 0=>array('label'=>'CompressSyslogs', 'jobtype'=>'method', 'class'=>'core/class/utils.class.php', 'objectname'=>'Utils', 'method'=>'compressSyslogs', 'parameters'=>'', 'comment'=>'PurgeDeleteTemporaryFiles', 'frequency'=>1, 'unitfrequency'=> 3600 * 24, 'priority'=>50, 'status'=>0, 'test'=>true), + ); } } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index d6514db4d2c..6648e43501e 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1444,6 +1444,9 @@ SyslogFilename=File name and path YouCanUseDOL_DATA_ROOT=You can use DOL_DATA_ROOT/dolibarr.log for a log file in Dolibarr "documents" directory. You can set a different path to store this file. ErrorUnknownSyslogConstant=Constant %s is not a known Syslog constant OnlyWindowsLOG_USER=Windows only supports LOG_USER +CompressSyslogs=Syslog files compression and backup +SyslogFileNumberOfSaves=Log backups +ConfigureCleaningCronjobToSetFrequencyOfSaves=Configure cleaning scheduled job to set log backup frequency ##### Donations ##### DonationsSetup=Donation module setup DonationsReceiptModel=Template of donation receipt