use File::ReadBackwards; use Getopt::Long;
use Time::Piece; use File::Find;
$time_pattern = '%Y-%m-%d %H:%M:%S';
$warning = 1;
$critical = 1;
$time_position = 0;
$result = GetOptions (
"pattern=s" => \$pattern, "logfile=s" => \$logfile, "interval=i" => \$interval, "timepattern=s" => \$time_pattern, "timeposition=i" => \$time_position, "warning|w=i" => \$warning, "critical|c=i" => \$critical, "debug|d|vv" => \$debug, "verbose|v" => \$verbose, "help|h|?" => \$usage );
print $count;
if ($usage || !(defined($pattern) && $pattern ne "") || !(defined($logfile) && $logfile ne "") || !(defined($interval) && $interval gt 0 )) {
print "\nUsage: $0
\t -pattern <regex-pattern>
\t -logfile <path to log file>
\t -interval <minutes>
\t [-timepattern <POSIX time pattern>]
\t [-warning|w <number_of_required_hits>] [-critical|c <number_of_required_hits>]
\t [-timeposition <time_string_index_on_line>] \n\n";
print "To allow for rotating logfiles, any file that matches the passed filename and was changed within the passed interval is checked. e.g. If you pass /var/log/applog, this could match /var/log/applog.0, /var/log/applog.old and so on. However, it does not handle compressed (e.g. gzip/bzip) files. \n\n";
print "Default time pattern is: %Y-%m-%d %H:%M:%S => 2012-12-31 17:20:40\n";
print "Example Time patterns (from a RHEL system):
BSD/Syslog: %b %d %H:%M:%S => Dec 31 17:20:40
Apache Logs: %d/%b/%Y:%H:%M:%S (with -timeposition 3) => 31/Dec/2012:17:20:40
Websphere Logs: %d-%b-%Y %I:%M:%S %p => 31-Dec-2012 05:20:40 PM
Nagios logs: %s => 1361260238 (seconds since 01-01-1970) \n";
print "For a posix time format documentation check out: http://linux.die.net/man/3/strftime \n\n";
print "Default warning/critical threshold of pattern matches to find is: 1 -> unless you change this, you will only get OK or CRITICAL, but never WARNING\n\n";
print "Default time position is 0 \n";
print "\t Time Position: each line is split into an array of strings on the space character, this provides the index for the first time string.\n";
print "\t Note: If the line starts with the time, that means we start at index 0.\n\n";
print "The values for interval and warning/critical need to be larger than zero \n";
exit;
}
my $now = localtime;
$oldestDate = $now - $interval*60;
if ($debug) { print "Now: $now and tzoffset: ". ($now)->tzoffset ."\n"; }
if ($debug) { print "Oldest date: $oldestDate and tzoffset: ". ($oldestDate)->tzoffset ."\n"; }
$hits = 0; $validFileNames = 0; my @dateFields = $time_pattern =~ / /g; my $dateFieldsCount = @dateFields;
if ($debug) {
$verbose = 1; print "Interval: $interval equals " . ($interval/1440) . " Fraction of days.\n";
}
$logfile=~m/^.+\//;
$DIR=$&;
@files = find(\&process, $DIR);
sub process {
if ($File::Find::name =~ m/$logfile/ && (-T)) { $validFileNames += 1;
if ($debug) { print "Found: $File::Find::name has age " . (-M) ." (in Fraction of days) \n"; }
if ((-M) < ($interval/1440)) {
$LOGS = File::ReadBackwards->new($File::Find::name) or
die "Can't read file: $File::Find::name\n";
while (defined($line = $LOGS->readline) ) {
my @fields = split ' ', $line; $dateString = ""; for ($i=0; $i <= $dateFieldsCount; $i++) {
$dateString .= $fields[$time_position + $i] . " "; }
$dateString =~ s/^\s+|\s+$//g ; $dateString =~ s/<|>|\]|\[//g ;
my $dt = Time::Piece->strptime($dateString, $time_pattern); my $dt_tzadjusted = ($dt - $now->tzoffset);
if ($dt->year eq 1970) {
$dt = $dt->add_years($now->year - 1970); $dt_tzadjusted = ($dt - $now->tzoffset);
if ($dt_tzadjusted > $now) {
$dt = $dt->add_years(-1);
$dt_tzadjusted = ($dt - $now->tzoffset);
}
}
if ($dt_tzadjusted > $oldestDate) { if ($line =~ m/$pattern/){ if ($debug) {print $dt . " => "; }
if ($verbose) { print $line; }
$hits++; }
}
else{
last; }
}
close(LOGS);
}
}
}
if ($hits >= ($critical + 0)) {
print "CRITICAL - There are $hits instances of \"$pattern\" in the last $interval minutes\n";
exit 2; }
if ($hits >= ($warning + 0)) {
print "WARNING - There are $hits instances of \"$pattern\" in the last $interval minutes\n";
exit 1; }
if ($validFileNames == 0) {
print "UNKNOWN - There were no files matching the passed filename: \"$logfile\"\n";
exit 3; }
else {
print "OK - There are only $hits instances of \"$pattern\" in the last $interval minutes - Warning threshold is $warning\n";
exit 0;
}