#!/usr/bin/perl -w use strict; use Getopt::Std; use Time::Local; use IO::File; use POSIX qw(strftime); use Data::Dumper; $|++; my %Opt = (); my @Conns = (); my %Range = (); use constant MIN => 0; # 32-bit "Thu Jan 1 00:00:00 1970" use constant MAX => 2147483647; # 32-bit "Tue Jan 19 03:14:07 2038" &GetArgs(); &GetConns(); &GetLogs(); sub GetArgs { my $Usage = qq{Usage: $0 [options] -h : This help message. -c : Specific connector - default is to list all connectors. -d : Specific direction - default is to list all directions -n : Trap name - default is to list all names -t : Time in stamp format mm/dd/yy-hh:mm or mm/dd/yy + - show entries created after specified stamp If time is not given, defaults to 23:59 - - show entries created before specified stamp If time is not given, default to 00:00 = - show entries created on specified stamp If time is not given it is ignored (all day) +- - show entries created between specified stamps If time is not given on first stamp, 00:00 is used If time is not given on second stamp, 23:59 is used Note: This includes the day(s) specified -s : Size of files caught in bytes + - show entries with files larger than specified size - - show entries with files smaller than specified size = - show entries with files equal to specified size +- - show entries with files between specified sizes } . "\n"; getopts( 'hc:d:n:t:s:', \%Opt ) or die "$Usage"; die "$Usage" if $Opt{h}; if ( $Opt{d} ) { $Opt{d} = lc( $Opt{d} ); die "$Usage" if ( $Opt{d} ne "in" && $Opt{d} ne "out" && $Opt{d} ne "both" ); } } sub GetConns { open( CONNECTORS, "/var/wt400/conf/_wtd.cfg" ) or die "Unable to open connector file!"; while () { next unless ( $_ =~ /^unit="(.*)"/ ); my $Conn = lc($1); next if ( $Conn eq "ins" || $Conn eq "ins2" || $Conn eq "_wtd" ); push @Conns, $Conn; } close(CONNECTORS); if ( $Opt{c} ) { $Opt{c} = lc( $Opt{c} ); if ( grep /\b$Opt{c}\b/, @Conns ) { @Conns = $Opt{c}; } else { die "\nInvalid connector - $Opt{c} !\n"; } } } sub GetLogs { my @Logs; foreach my $Conn (@Conns) { my @Directions; if ( $Opt{d} ) { @Directions = $Opt{d}; } else { @Directions = (qw(in out both)); } foreach my $Dir (@Directions) { push @Logs, "/var/spool/wt400/log/$Conn/trap_${Dir}.log" if ( -r "/var/spool/wt400/log/$Conn/trap_${Dir}.log" && -s _ ); } } unless (@Logs) { die "\nUnable to find any logs!\n"; } else { %Range = getRange(); # MAKE A FILEHANDLE FOR EACH FILE WE WERE GIVEN my @files = map { new IO::File $_ or die "could not open $_: $!" } @Logs; # READ IN A LINE FOR EACH FILE my @lines = map { scalar(<$_>) } @files; # GET THE DATES FOR EACH LINE; my @dates = map { (m/^\s*(\d+)\s+/) } @lines; my $found; do { # FIND THE LINE WITH THE EARLIEST DATE my $min = MAX; $found = undef; for ( my $i = 0 ; $i < @Logs ; $i++ ) { my $num = $dates[$i]; if ( $num < $min ) { $found = $i; $min = $num; } } if ( defined($found) ) { # IF WE FOUND A LINE, SHOW IT AND READ THE NEXT # LINE IN FOR THAT LOG FILE prettyPrint( $lines[$found], $Logs[$found] ); my $io = $files[$found]; if ( defined( $_ = <$io> ) ) { $lines[$found] = $_; ( $dates[$found] ) = (m/^\s*(\d+)\s+/); } else { # Delete this log off the queues. splice @files, $found, 1; splice @lines, $found, 1; splice @dates, $found, 1; splice @Logs, $found, 1; } } } while ( defined($found) ); } } # Update the desired range defaults (from command line) sub getRange { my %range = ( start => MIN, end => MAX, ); if ( $Opt{t} ) { $Opt{t} =~ s/\s+//; # delete ws if ( $Opt{t} =~ /^\+(.*)/ ) { $range{start} = getStamp( "after", $1 ); } elsif ( $Opt{t} =~ /^\-(.*)/ ) { $range{end} = getStamp( "before", $1 ); } elsif ( $Opt{t} =~ /^\=(.*)/ ) { $range{start} = getStamp( "before", $1 ); $range{end} = getStamp( "after", $1 ); } elsif ( $Opt{t} =~ /^(.*)\+\-(.*)/ ) { $range{start} = getStamp( "before", $1 ); $range{end} = getStamp( "after", $2 ); } } if ( $range{start} < 0 || $range{end} < 0 ) { die "invalid range created"; } return %range; } # Get a timestamp from a formatted date sub getStamp { # '$before_after' decides what the default value # for $hour & $min will be: 00:00 or 23:59. my $before_after = $_[0]; my ( $mon, $day, $year, $hour, $min ) = split ?[-/:]?, $_[1]; if ( $before_after eq "before" ) { ( $hour ||= 00, $min ||= 00 ); } elsif ( $before_after eq "after" ) { ( $hour ||= 23, $min ||= 59 ); } else { return undef; # error: undefined behaviour } return timelocal( 0, $min, $hour, $day, $mon - 1, $year + 100 ); } # Print out the line in a nice way sub prettyPrint { my $Line = $_[0]; my $File = $_[1]; my @Fields = split " ", $Line; # Check that the line is in date range return unless ( $Fields[0] >= $Range{start} && $Fields[0] <= $Range{end} ); if ( $Opt{n} ) { return unless ( lc( $Opt{n} ) eq lc( $Fields[3] ) ); } if ( $Opt{s} ) { $Opt{s} =~ s/\s+//; # delete ws if ( $Opt{s} =~ /^\+(.*)/ ) { return unless ( $Fields[2] > $1 ); } elsif ( $Opt{s} =~ /^\-(.*)/ ) { return unless ( $Fields[2] < $1 ); } elsif ( $Opt{s} =~ /^\=(.*)/ ) { return unless ( $Fields[2] == $1 ); } elsif ( $Opt{s} =~ /^(.*)\+\-(.*)/ ) { return unless ( $Fields[2] >= $1 && $Fields[2] <= $2 ); } } if ( $File =~ m{^.*/(.*)/trap_(.*)\.log} ) { my $Conn = $1; my $Dir = $2; my $Time = strftime( "[%x-%X]", localtime( $Fields[0] ) ); print "$Time $Conn $Dir $Fields[3] $Fields[1] $Fields[2]\n"; } }