#!/usr/pubsw/bin/perl #$DEBUG++ ; ####################################################################### # # arclog - reads first line of log and figures out where to archive # the file. # # $Id: arclog,v 1.8 1997/11/13 23:18:15 bbense Exp $ # # # # Usage: arclog -c logfiles # Options: -c # Input: filesnames and compress # Output: (return value, arguments, files ...) # Algorithm: # Subordinate modules: ( - ) # # $Log: arclog,v $ # Revision 1.8 1997/11/13 23:18:15 bbense # minor tweaks # # Revision 1.7 1997/01/06 19:37:28 bbense # Fixed?? # # Revision 1.6 1997/01/06 19:11:48 bbense # Fixed year end bug # # Revision 1.5 1996/09/03 17:37:51 bbense # typo in mkdir # # Revision 1.4 1996/07/25 22:19:30 bbense # Documentation clean up # # Revision 1.3 1996/07/25 19:19:58 bbense # II # # #---------------------------------------------------------------------- # Copyright (c) 1996 Board of Trustees, Leland Stanford Jr. University ####################################################################### =head1 NAME arclog - reads the first line of a syslog file,then archives it. =head1 SYNOPSIS arclog [-RCxvh][-t title] [-e file_ext ] -p[perl filter file] [-c ] [-b ][-y year] files =head1 DESCRIPTION This program can be used to archive syslog format files. It reads the first line of the file to determine where to archive the file. For example: Jun 20 10:50:12 boron sendmail[28402]: KAA28402: ldap foo => foo@leland.stanford.edu will be archived in /1996/Jun96/boron.Jun20 The options are: =over 4 =item -R Remove the original log file after copying to the archive. Default is to leave it in place. =item -C Compress the copy of the log file. The default filter is gzip C<-c> . Compressed logs have a .gz extension by default. =item -b The base directory of the archive. =item -p Reads in the perl file which contains a routine called log_filter. This routine takes a single line of the syslog file and returns the line to be archived (possibly null). Null lines are not archived. Here's an example for a TACACS server: sub log_filter { my($line) = @_ ; if ( $line =~ m/STAT/ ) { return $line ; } else { return "" ; } } 1; Since this file is "required" you can do other unreccomended things like overriding the command line options. For example : $opt_b = '/my/log/home' ; sub log_filter { . . } 1; Unfortunately, this file is processed after the command line options, so this kind of configuration CANNOT be overidden by the command line. =item -c Use the given program as a compression filter, for example. arclog C<-C> C<-c> "gzip C<-c>" logfile is the same as arclog C<-C> logfile. The filter must read from stdin and write to stdout. =item -e Add . Use as the title of the archive log. The default is to use the host from the first line of the log file. =item -h Print usage message and quit. =item -x Extra debugging output. =item -y <4digit year> Use argument as year index ( rather than now. ) This is not needed for the Dec/Jan transition. i.e. If you archive a file with a year from when it was written it will be archived in the correct year. =back =head1 AUTHOR Booker C. Bense : bbense@networking.stanford.edu =cut $0 =~ s,.*/,,; # use basename only $VERSION = sprintf("%d.%02d", q$Revision: 1.8 $ =~ /(\d+)\.(\d+)/); # Parse command line use Getopt::Std; $opt_R = undef; # remove log after copy $opt_C = undef; # Compress copy $opt_b = '/local/archive/logs'; # base directory for archive $DEBUG && ( $opt_b = '.') ; $opt_c = '/usr/local/bin/gzip -c'; # compression filter $opt_e = 'gz' ; # file extension $opt_p = undef; # perl filter $opt_h = undef; # print usage $opt_v = undef; # print version $opt_x = undef; # extra debugging info $opt_t = undef ; unless (getopts("xhRCv:b:c:e:y:t:p:")) { usage(); } if ( $opt_h || $opt_v ) { usage(); } unless ( $opt_C ) { $opt_c = '/bin/cat' ; } sub trivial { my ( $line ) = @_ ; return $line ; } if ( $opt_p ) { require $opt_p ; $log_filter = \&log_filter ; } else { $log_filter = \&trivial ; } # What time is it ? %Monthes = ( "Jan", 0, "Feb", 1, "Mar", 2, "Apr", 3, "May", 4, "Jun", 5, "Jul", 6, "Aug", 7, "Sep", 8, "Oct", 9, "Nov", 10, "Dec", 11 ) ; $now = time ; ($sec,$min,$hour,$mday,$mon,$year,$wday) = (localtime($now))[0,1,2,3,4,5,6]; $century =( $year > 99 ) ? '20' : '19' ; # If anyone is still using this # in 2071, they can fix it. $this_year = $year + 1900; while ( $logfile = shift ) { unless ( open(LOG,"< $logfile" ) ) { print "Can not read $logfile\n" ; next ; } $year = $this_year ; $Line = ; # Build file name @Line = split(/[\s]+/,$Line); $Month = $Line[0] ; $Day = $Line[1] ; $Host = $opt_t || $Line[3] ; $name = "$Host.$Month$Day" ; # Copy to archive if ( $Monthes{ $Month } > $mon ) { $year-- ; # Archiving December files in January. } $fyear = $opt_y || "$year" ; # $path = "$opt_b/$fyear" ; $opt_x && print "Looking for $path\n" ; if ( ! -d $path ) { mkdir($path, 0755 ) || die "Can not create $path\n" ; } $path .= "/$Month" ; $opt_x && print "Looking for $path\n" ; if ( ! -d $path ) { mkdir($path, 0755 ) || die "Can not create $path\n" ; } $arc_file = "$path/$name" ; if ( $opt_C ) { $arc_file .= ".$opt_e" ; } $opt_x && print "Looking for $arc_file\n" ; if ( -f $arc_file ) { print STDERR "$logfile already archived as $arc_file, skipping\n" ; next ; } $opt_x && print "Archiving $logfile | $opt_c > $arc_file\n" ; open(ARC,"| $opt_c > $arc_file") || die "Can not write $arc_file\n" ; print ARC $Line ; while ( ) { # need to do some magic here... $print_line = &{$log_filter}($_) ; $DEBUG && print "line:$print_line:$_" ; if ( $print_line ) { (print ARC $print_line ) || die "Error in writing $arc_file\n" ; } } # Clean up close(ARC); close(LOG); if ( $opt_R ) { unlink $logfile ; } } sub usage { print "$0 : $VERSION\n" ; print "Usage:\n\t" ; print "arclog -R -C -h -t -b <directory> -p <perl filter> -c <compression filter> -e <file_extension> -y <year> logfiles\n" ; exit ; }