OpenWetWare:Software/Server/Urchin/Log Rotation/WebLogRotate
- !/usr/bin/perl -w
- RCS ID: $Revision: 1.7 $
- Script to rotate the specified logs and name them with yesterday's
- date. The script also restarts the web server with a specified command.
- and optionally compresses old logs and removes them after a certain period.
- Copyright (c) 2002, 2003, 2004 Urchin Software Corporation
- Usage: weblog_rotate.pl [--log /path/to/log [--log /path/to/log] \
- | [--loglist /path/to/loglist]] \
- --touchlog \
- --restart_cmd "apachectl restart" \
- --compress --days N --help
- Where:
- --loglist specifies the path to a file containing the full pathnames
- of all the logs that are to be rotated. This option cannot be used
- with the --log option.
- --log specifies the full path to the log file to be rotated
- (multiple --log entries are allowed)
- --touchlog specifies that a new log should be created once the
- original log is rotated.
- (default is not to create the log)
- --restart_cmd specifies the command to restart the web server
- (default is apachectl restart)
- --compress specifies whether or not to compress the logs with gzip
- (default is off)
- --noprune disables automatic pruning of archived logs
- (default is off)
- --days specifies how many days to keep archived logs
- (default is 60, minimum value is 1)
- --help shows this message\n\n";
use strict; use Time::localtime; use Getopt::Long;
- Initialize variables
my @logs = (); my $loglistfile = ""; my $restart_cmd = "apachectl restart"; my $days = 60; my $compress = 0; my $noprune = 0; my $touchlog = 0; my $gstatus; my $abslogpath; my $help = 0;
- Read in the options
$gstatus = GetOptions('loglist=s' => \$loglistfile, 'log=s' => \@logs, 'restart_cmd=s' => \$restart_cmd, 'noprune' => \$noprune, 'days=i' => \$days, 'touchlog' => \$touchlog, 'compress' => \$compress, 'help' => \$help); if ($help) { &Usage; exit; } if ($gstatus ne 1) { &Usage; exit(1); }
if ( $loglistfile ne "" ) { if ( @logs ) { print "FATAL error: \"--log\" and \"--loglist\" options are mutually exclusive\n"; &Usage; exit(1); } open(LOGLISTFILE, $loglistfile) || die "FATAL error: can't open log list file $loglistfile\n"; @logs = <LOGLISTFILE>; }
- Calculate the date string for 'yesterday'
my $yesterday = convert_epoch(time() - 86400);
- Ensure that '$days' is at least 1
if ($days <= 0) { $days = 1; }
- Calculate the date string for '$days' ago
my $cutoff_date = convert_epoch(time() - ($days * 86400));
- Rotate each log file inside its current directory
my ($log, $new_log, $dir); my ($mode, $uid, $gid); foreach $log (@logs) { chomp($log); # Create the name for the new log $new_log = "$log.$yesterday";
# Verify that $log exists and is readable if ((!-e $log) && (!-r $log)) { warn "Logfile: $log does not exist or is unreadable\n"; next; }
# Move $log to $new_log as long as it doesn't overwrite another file if ((-e $new_log) || ((-e "$new_log.gz") && $compress)) { warn "Logfile: $new_log already exists. Skipping rotation...\n"; } else { rename($log, $new_log) || warn "Unable to rename: $log to $new_log"; if ( $touchlog ) { ($mode,$uid,$gid) = (stat("$new_log"))[2,4,5]; open(LOG,"+>$log") || warn "Unable to create $log"; close(LOG); chown($uid,$gid,$log) || warn "Unable to change ownership/group of $log to UID $uid/GID $gid"; chmod($mode,$log) || warn "Unable to change permissions of $log to $mode"; } } }
- Restart the web server
if ($restart_cmd) { system($restart_cmd) && warn "$restart_cmd failed to restart web server properly"; }
- Loop through logs and prune and/or gzip as necessary.
foreach $log (@logs) { # Create the name for the new log $new_log = "$log.$yesterday";
# Determine the directory where the log file is located $_ = $log; ($dir) = m#(^/.*/)#;
# Compress the logs if set as option if ($compress) { # Verify that $new_log exists and is readable and compress the log if ((!-e $new_log) && (!-r $new_log)) { warn "Cannot compress $new_log since it does not exist or is not readable"; next; } else { system("/usr/bin/gzip $new_log") && warn "Problems gzipping $new_log"; } }
# Go to the next log if log pruning is disabled if ($noprune) { print "Skipping log pruning for $log\n"; next; }
# Remove outdated logs from the directory opendir(DIR, $dir) || warn "Unable to open archived logs directory: $dir"; while (my $file = readdir(DIR)) { $abslogpath = "$dir$file"; # Skip logs that don't match the same base logfile name if ( index($abslogpath,$log) == -1 ) { next; } # Skip remaining logs that don't have a YYYYMMDD suffix pattern if ($file =~ /(\d{8})/) { if ($1 < $cutoff_date) { unlink("$dir$file") || warn "Problems removing file: $dir$file"; } } } }
- Subroutine to show the usage of this script
sub convert_epoch { my $rawtime = $_[0]; my $formatedtime = "";
if ((! defined($rawtime)) || $rawtime eq "") { $formatedtime = 0; } else { $rawtime = localtime($rawtime); $formatedtime = sprintf("%04d%02d%02d", $rawtime->year+1900, $rawtime->mon+1, $rawtime->mday); } return($formatedtime); }
sub Usage {
print "Usage: $0 [--loglist /path/to/loglist || --log /path/to/log [--log /path/to/log] ] \\
--touchlog \\
--restart_cmd \"apachectl restart\" \\ --compress [--noprune | --days N] --help
Where: --loglist specifies the path to a file containing the full pathnames of all the logs that are to be rotated. This option cannot be used with the --log option. --log specifies the full path to the log file to be rotated (multiple --log entries are allowed) --touchlog specifies that a new log should be created once the original log is rotated.
(default is not to create the log)
--restart_cmd specifies the command to restart the web server (default is apachectl restart) --compress specifies whether or not to compress the logs with gzip (default is off) --noprune disables automatic pruning of archived logs (default is off) --days specifies how many days to keep archived logs (default is 60, minimum value is 1) --help shows this message\n\n";
}