From: Frank Brehm Date: Mon, 27 Jun 2011 15:46:52 +0000 (+0000) Subject: Mit Logrotating weitergemacht X-Git-Url: https://git.uhu-banane.de/?a=commitdiff_plain;h=77fee406d66528be3ae2218c053fefc3a0da9d9a;p=my-stuff%2Fpy-logrotate.git Mit Logrotating weitergemacht git-svn-id: http://svn.brehm-online.com/svn/my-stuff/python/PyLogrotate/trunk@262 ec8d2aa5-1599-4edb-8739-2b3a1bc399aa --- diff --git a/LogRotateConfig.py b/LogRotateConfig.py index 5eecbda..791999d 100755 --- a/LogRotateConfig.py +++ b/LogRotateConfig.py @@ -817,9 +817,11 @@ class LogrotateConfigurationReader(object): ( _("Needless content found at the end of a logfile definition found: '%(rest)s' (file '%(file)s', line %(line)s)") % { 'rest': str(rest), 'file': configfile, 'line': linenr}) ) + if self.new_log['size']: + self.new_log['ifempty'] = False + found_files = self._assign_logfiles() if self.verbose > 3: self.logger.debug( ( _("New logfile definition:") + "\n" + pp.pformat(self.new_log))) - found_files = self._assign_logfiles() if found_files > 0: self.config.append(self.new_log) in_fd = False diff --git a/LogRotateHandler.py b/LogRotateHandler.py index fcf6597..d7c89b1 100755 --- a/LogRotateHandler.py +++ b/LogRotateHandler.py @@ -24,12 +24,15 @@ import os import os.path import errno import socket +import subprocess +from datetime import datetime, timedelta from LogRotateConfig import LogrotateConfigurationError from LogRotateConfig import LogrotateConfigurationReader from LogRotateStatusFile import LogrotateStatusFileError from LogRotateStatusFile import LogrotateStatusFile +from LogRotateStatusFile import utc revision = '$Revision$' revision = re.sub( r'\$', '', revision ) @@ -573,10 +576,183 @@ class LogrotateHandler(object): "\n" + pp.pformat(definition) self.logger.debug(msg) - + for logfile in definition['files']: + if self.verbose > 1: + msg = ( _("Performing logfile '%s' ...") % (logfile)) + "\n" + self.logger.debug(msg) + should_rotate = self._should_rotate(logfile, definition) + if self.verbose > 1: + if should_rotate: + msg = _("logfile '%s' WILL rotated.") + else: + msg = _("logfile '%s' will NOT rotated.") + self.logger.debug(msg % (logfile)) + if not should_rotate: + continue + self._rotate_file(logfile, definition) return + #------------------------------------------------------------ + def _rotate_file(self, logfile, definition): + ''' + Rotates a logfile with all with all necessary actions before + and after rotation. + + Throughs an LogrotateHandlerError on error. + + @param logfile: the logfile to rotate + @type logfile: str + @param definition: definitions from configuration file + @type definition: dict + + @return: None + ''' + + _ = self.t.lgettext + + sharedscripts = definition['sharedscripts'] + firstscript = definition['firstaction'] + prescript = definition['prerotate'] + postscript = definition['postrotate'] + lastscript = definition['lastaction'] + + # Executing of the firstaction script, if it wasn't executed + if firstscript: + if self.verbose > 2: + msg = _("Looking, whether the firstaction script should be executed.") + self.logger.debug(msg) + if not self.scripts[firstscript]['first']: + msg = _("Executing firstaction script '%s' ...") % (firstscript) + self.logger.info(msg) + if not self.test: + cmd = '\n'.join(self.scripts[firstscript]['cmd']) + if not self._execute_command(cmd): + return + self.scripts[firstscript]['first'] = True + + # + + #------------------------------------------------------------ + def _execute_command(self, command): + ''' + Executes the given command as an OS command in a shell. + + @param command: the command to execute + @type command: str + + @return: Success of the comand (shell returncode == 0) + @rtype: bool + ''' + + _ = self.t.lgettext + if self.verbose > 3: + msg = _("Executing command: '%s'") % (command) + self.logger.debug(msg) + try: + retcode = subprocess.call(command, shell=True) + if self.verbose > 3: + msg = _("Got returncode: '%s'") % (retcode) + self.logger.debug(msg) + if retcode < 0: + msg = _("Child was terminated by signal %d") % (-retcode) + self.logger.error(msg) + return False + if retcode > 0: + return False + return True + except OSError, e: + msg = _("Execution failed: %s") % (str(e)) + self.logger.error(msg) + return False + + return False + + #------------------------------------------------------------ + def _should_rotate(self, logfile, definition): + ''' + Determines, whether a logfile should rotated dependend on + the informations in the definition. + + Throughs an LogrotateHandlerError on harder errors. + + @param logfile: the logfile to inspect + @type logfile: str + @param definition: definitions from configuration file + @type definition: dict + + @return: to rotate or not + @rtype: bool + ''' + + _ = self.t.lgettext + + if self.verbose > 2: + msg = _("Check, whether logfile '%s' should rotated.") % (logfile) + self.logger.debug(msg) + + if not os.path.exists(logfile): + msg = _("logfile '%s' doesn't exists, not rotated") % (logfile) + if not definition['missingok']: + self.logger.error(msg) + else: + if self.verbose > 1: + self.logger.debug(msg) + return False + + if not os.path.isfile(logfile): + msg = _("logfile '%s' is not a regular file, not rotated") % (logfile) + self.logger.warning(msg) + return False + + filesize = os.path.getsize(logfile) + if self.verbose > 2: + msg = _("Filesize of '%(file)s': %(size)d") % {'file': logfile, 'size': filesize} + self.logger.debug(msg) + + if not filesize: + if not definition['ifempty']: + if self.verbose > 1: + msg = _("Logfile '%s' has a filesize of Zero, not rotated") % (logfile) + self.logger.debug(msg) + return False + + if self.force: + if self.verbose > 1: + msg = _("Rotating of '%s' because of force mode.") % (logfile) + self.logger.debug(msg) + return True + + maxsize = definition['size'] + if maxsize is None: + maxsize = 0 + + last_rotated = self.state_file.get_rotation_date(logfile) + if self.verbose > 2: + msg = _("Date of last rotation: %s") %(last_rotated.isoformat(' ')) + self.logger.debug(msg) + next_rotation = last_rotated + timedelta(days = definition['period']) + if self.verbose > 2: + msg = _("Date of next rotation: %s") %(next_rotation.isoformat(' ')) + self.logger.debug(msg) + + if filesize < maxsize: + if self.verbose > 1: + msg = _("Filesize %(filesize)d is less than %(maxsize)d, rotation not necessary.") \ + % {'filesize': filesize, 'maxsize': maxsize} + self.logger.debug(msg) + return False + + curdate = datetime.utcnow().replace(tzinfo = utc) + if next_rotation > curdate: + if self.verbose > 1: + msg = _("Date of next rotation '%(next)s' is in future, rotation not necessary.") \ + % {'next': next_rotation.isoformat(' ')} + self.logger.debug(msg) + return False + + return True + #------------------------------------------------------------ def delete_oldfiles(self): pass diff --git a/LogRotateStatusFile.py b/LogRotateStatusFile.py index 7553705..4313208 100755 --- a/LogRotateStatusFile.py +++ b/LogRotateStatusFile.py @@ -267,7 +267,7 @@ class LogrotateStatusFile(object): if not self.was_read: self._read(must_exists = False) - rotate_date = datetime.min() + rotate_date = datetime.min.replace(tzinfo=utc) if logfile in self.file_state: rotate_date = self.file_state[logfile] diff --git a/logrotate.py b/logrotate.py index 7ce1dc6..953a69c 100755 --- a/logrotate.py +++ b/logrotate.py @@ -17,6 +17,7 @@ import re import sys import pprint import gettext +import os import os.path from datetime import datetime @@ -40,6 +41,9 @@ __license__ = 'GPL3' #----------------------------------------------------------------- def main(): + # unbuffered output to stdout + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) + basedir = os.path.realpath(os.path.dirname(sys.argv[0])) #print "Basedir: %s" % ( basedir ) local_dir = os.path.join(basedir, 'po') diff --git a/test/apache2 b/test/apache2 index 680ac24..2ae67d9 100644 --- a/test/apache2 +++ b/test/apache2 @@ -3,42 +3,42 @@ # pidfile /home/frank/Development/Python/PyLogrotate/logrotate.pid +statusfile /home/frank/Development/Python/PyLogrotate/logrotate.status -/var/log/apache2/access_log { - missingok - notifempty - sharedscripts - rotate 10 - dateext - daily - size 5M - maxage 0.5y - mail test@uhu-banane.de - olddir /var/log/apache2/%Y-%m 0755 apache users - postrotate - /etc/init.d/apache2 reload > /dev/null 2>&1 || true - endscript +/home/frank/devel/Python/PyLogrotate/test/log/access_log { + missingok + notifempty + sharedscripts + rotate 10 + dateext + daily + size 5K + maxage 0.5y + mail test@uhu-banane.de + olddir /var/log/apache2/%Y-%m 0755 apache users + postrotate + echo "/etc/init.d/apache2 reload > /dev/null 2>&1 || true" + endscript } -/var/log/apache2/access_log -/var/log/apache2/*.log -{ - missingok - notifempty - sharedscripts - rotate 10 - #dateext '%Y%m%d' - dateext - #error bla - weekly - #period 4.5days 2 hours 3.4y - size 1M - maxage 0.5y - mail test@uhu-banane.de - #olddir /var/log/apache2/%Y-%m - olddir /var/log/apache2/%Y-%m 0755 apache users - postrotate - /etc/init.d/apache2 reload > /dev/null 2>&1 || true - endscript +/home/frank/devel/Python/PyLogrotate/test/log/*.log { + missingok + notifempty + sharedscripts + rotate 10 + #dateext '%Y%m%d' + dateext + #error bla + weekly + #period 4.5days 2 hours 3.4y + size 1K + maxage 0.5y + mail test@uhu-banane.de + #olddir /var/log/apache2/%Y-%m + olddir /var/log/apache2/%Y-%m 0755 apache users + postrotate + echo "/etc/init.d/apache2 reload > /dev/null 2>&1 || true" + endscript } +# vim: ts=4 expandtab