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