#!/usr/bin/perl -w # # cron.cutsyslog # John Simpson 1999-04-05 # # cuts syslog files, parses them by date, and backs them up # # 2003-03-05 jms1 - minor code cleanups, added the copyright and license # text you see above. added the ability to use a 0 day count to turn # off deletion of old files. # # 2005-04-09 jms1 - changed copyright notice to indicate my intention # that this code is licensed under GPL version 2 only, rather than # GPL version 2 "or later". # # 2008-10-14 jms1 - fixed typos in the chown() and chmod() calls within the # fh() function. # ############################################################################### # # Copyright (C) 1999-2005 John Simpson. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # or visit http://www.gnu.org/licenses/gpl.txt # ############################################################################### require 5.003 ; use strict ; use Carp ; use FileHandle ; use lib "/usr/local/lib" ; use Logit ; ############################################################################### # # configuration my $do_cut = 1 ; # during testing, the cut files were already there # and i had 0 here. my $restart = "/etc/init.d/syslog restart" ; my $mkdir = "/bin/mkdir" ; my $cp = "/bin/cp" ; my $scp = "/usr/bin/scp" ; my $bserver = "" ; my $bport = 22 ; my $buserid = "" ; my $bkey = "" ; my $bdir = "" ; $Logit::fac = "local2" ; $Logit::stdout = 0 ; my %logfiles = ( "/var/log/maillog" => 30 , "/var/log/messages" => 30 , ) ; ############################################################################### # # figure the date for a given syslog line my %mnum = ( "Jan" => 1 , "Feb" => 2 , "Mar" => 3 , "Apr" => 4 , "May" => 5 , "Jun" => 6 , "Jul" => 7 , "Aug" => 8 , "Sep" => 9 , "Oct" => 10 , "Nov" => 11 , "Dec" => 12 ) ; sub linedate($) { my ( $smo , $day ) = split ( /\s+/ , $_[0] ) ; my ( $month ) = $mnum{$smo} || 0 ; my ( @d ) = localtime ; my ( $year ) = $d[5] + 1900 ; my ( $thismo ) = $d[4] + 1 ; if ( ( 1 == $thismo ) && ( 12 == $month ) ) { $year -- ; } return sprintf ( "%04d%02d%02d" , $year , $month , $day ) ; } ############################################################################### # # remove "old" versions of a file sub delbut($$) { my ( $pat , $cnt ) = @_ ; my ( @files ) = glob ( $pat ) ; my ( $f ) ; for $f ( reverse sort @files ) { if ( $cnt ) { logit "Ignoring $f\n" ; $cnt -- ; } else { logit "Deleting $f\n" ; unlink $f ; } } } ############################################################################### # # cache file handles for output files my ( %fhandle , %fhp , %fhu , %fhg ) ; sub fh($$$$) { my $name = shift ; my $perm = shift ; my $uid = shift ; my $gid = shift ; if ( exists $fhandle{$name} ) { return $fhandle{$name} ; } my ( $dn ) = $name ; $dn =~ s/\/[^\/]+$// ; system "$mkdir -p -m 0755 $dn" ; my ( $n ) = new FileHandle ">>$name" ; bad "Can\'t append to $name: $!" unless ( defined $n ) ; logit "Adding data to $name" ; $fhp{$name} = $perm ; $fhu{$name} = $uid ; $fhg{$name} = $gid ; chown $fhu{$name} , $fhg{$name} , $name ; chmod $fhp{$name} , $name ; $fhandle{$name} = $n ; return $n ; } ############################################################################### # # close all of the file handles sub closefh() { my ( $f , $h ) ; for $f ( sort keys %fhandle ) { $h = $fhandle{$f} ; close $h ; delete $fhandle{$f} ; chown $fhu{$f} , $fhg{$f} , $f ; # in case the ones in chmod $fhp{$f} , $f ; # fh() don't work } } ############################################################################### ############################################################################### ############################################################################### # # main processing starts here my ( $f , @s , $line , $date , $of , $h , %lc , @if , @rf ) ; logit "Starting" ; ######################################## # cut the log files off if ( $do_cut ) { for $f ( sort keys %logfiles ) { @s = stat ( $f ) ; unless ( $#s > -1 ) { logit "stat($f): $!" ; next ; } if ( rename ( $f , "$f.cut" ) ) { logit "Renamed $f to $f.cut" ; push ( @if , $f ) ; if ( open ( O , ">$f" ) ) { close O ; chown $s[4] , $s[5] , $f ; chmod $s[2] , $f ; } else { logit "Can\'t create new $f: $!" ; } } else { logit "Can\'t rename $f to $f.cut: $!" ; } } } else { @if = sort keys %logfiles ; } ######################################## # restart syslogd logit "Restarting syslogd" ; system $restart ; logit "syslogd restart complete" ; ######################################## # parse the cut-off files into per-date files for $f ( @if ) { @s = stat ( "$f.cut" ) ; unless ( $#s > -1 ) { logit "stat($f.cut): $!" ; next ; } unless ( open ( I , "<$f.cut" ) ) { logit "open($f.cut): $!\n" ; next ; } push ( @rf , $f ) ; logit "Reading $f.cut" ; while ( defined ( $line = ) ) { $date = linedate ( $line ) ; $of = "$f.$date" ; $h = fh ( $of , $s[2] , $s[4] , $s[5] ) ; # perm,uid,gid print $h $line ; $lc{$of} ++ ; } logit "Closing $f.cut" ; close I ; } ######################################## # close the output files closefh() ; for $f ( sort keys %lc ) { logit "Wrote $lc{$f} lines to $f" ; } ######################################## # backup the daily files we have changed if ( $bserver ) { for $f ( sort keys %lc ) { my ( $cmd ) ; logit "Backing up $f to $bserver" ; $cmd = $scp . ( $bport ? " -P $bport" : "" ) . ( $bkey ? " -o \'IdentityFile2 $bkey\'" : "" ) . " $f $buserid\@$bserver:$bdir/" ; logit ">>> $cmd" ; system $cmd ; } } elsif ( $bdir ) { for $f ( sort keys %lc ) { my ( $cmd ) ; logit "Backing up $f" ; $cmd = "$cp -f $f $bdir/" ; logit ">>> $cmd" ; system $cmd ; } } ######################################## # delete the "*.cut" files for $f ( @rf ) { logit "Removing $f.cut" ; unlink "$f.cut" ; } ######################################## # cleanup logit "Cleaning up old log files" ; for $f ( sort keys %logfiles ) { if ( $logfiles{$f} ) { delbut ( "$f.*" , $logfiles{$f} ) ; } } ######################################## # outta here logit "Done" ;