rendered paste body#!/usr/bin/perl -w
# Load modules
use Switch;
use IO::Seekable;
use IO::Handle;
# Init vars
%logs = ('mx','/sonic-logs/mail/maillog.mx',
'mail','/sonic-logs/mail/maillog.mail',
'rad','/sonic-logs/radmon/today',
'dhcp','/sonic-logs/dhcpd/dhcpd.log',
'pop','/sonic-logs/mail/popper',
'pwd','/sonic-info/passwd-withgcos');
$match = 0;
$lines = 0;
$help = " Usage: dst [OPTIONS] [LOG] STRING
Description: Looks through [LOG] for lines that contain STRING
Behavior:
-t Given log is tailed
-f Follows the end of the file
-w Searches for exact word matches
-i Case insensitive search
-v Display verbose options on script initiation
-n [LINES] Implies tail, set number to lines to [LINES]
LOG may include any of the following...
mail(default) Parse $logs{'mail'}
mx Parse $logs{'mx'}
pop Parse $logs{'pop'}
rad Parse $logs{'rad'}
pwd Parse $logs{'pwd'}
dhcp Parse $logs{'dhcp'}
Miscellaneous:
--help Displays this help \n\n\n";
# By default we will match anything
$string = 'ANY';
# By default we don't tail the log
$tail = 0;
# By default we don't follow a growing log
$follow = 0;
# By default search is case sensitive
$case = 1;
# Default string (will be replaced by $string)
$pattern = 'STRING';
# Do not show verbose output by default
$verbose = 0;
# Number of lines we're shooting to tail
$tlines = 10000;
# Our default log file
$log = 'mail';
# Set our line length for default log
$seek = -250;
# As we go through arguments lets pay attention to which one we're looking at
$key = 0;
# Parse arguments
if ($#ARGV > -1) {
foreach (@ARGV) {
switch ($_) {
case '--help' { die($help) }
# Parse flags
case m/^-/ {
if($_ =~ m/f/) { $follow = 1; }
if($_ =~ m/n/) {
if($ARGV[($key+1)] =~ m/[0-9]+/) {
$tlines = $ARGV[($key+1)];
$tail = 1;
}
}
if($_ =~ m/v/) { $verbose = 1; }
if($_ =~ m/t/) { $tail = 1; }
if($_ =~ m/i/) { $case = 0; }
if($_ =~ m/v/) { $verbose = 1; }
if($_ =~ m/w/) { $pattern = '[^a-zA-Z0-9_]STRING[^a-zA-Z0-9_]'; }
}
case /^mail$|^mx$|^rad$|^dhcp$|^pop$|^pwd$/ {
# Pick a log to parse
$log = $_;
# Set byte value for a line in each log so we can seek back for our tail
switch($_) {
case 'mail' { $seek = -250; }
case 'mx' { $seek = -250; }
case 'rad' { $seek = -100; }
case 'dhcp' { $seek = -200; }
case 'pop' { $seek = -100; }
case 'pwd' { $seek = -100; }
}
}
# If the last argument isn't an option we'll search for it
else { if($_ eq $ARGV[-1] & $_ ne $tlines) { $string = $_; } }
}
$key++;
}
}
$pattern =~ s/STRING/$string/;
if($string ne 'ANY') { print 'Checking for instances of "'.$string.'" in file "'.$logs{$log}.'"'; }
if($verbose | $string ne 'ANY') { print "\nMatch Case: ".($case ? 'TRUE' : 'FALSE')."\nTailing log: ".($tail ? 'TRUE' : 'FALSE')."\nFollows log: ".($follow ? 'TRUE' : 'FALSE')."\nExact Match: ".($pattern eq $string ? 'FALSE' : 'TRUE'); }
print "\n\n";
# Open log for parsing
open(LOGF, $logs{$log}) || die 'Didn\'t work.';
# If we're tailing, go to tail position
if($tail) { seek(LOGF,$seek*$tlines,SEEK_END) }
FOLLOW:
while (<LOGF>) {
if($tail) { $lines++; }
if($string ne 'ANY') {
if($case == 0) {
if($_ =~ m/$pattern/i) {
$match++;
print $_;
}
}
else {
if($_ =~ m/$pattern/) {
$match++;
print $_;
}
}
}
else { print $_; }
}
# If we're following the file let's wait a couple seconds then clear EOF before continuing
if($follow) {
sleep(5);
LOGF->clearerr();
goto FOLLOW;
}
close(LOGF);
if($string ne 'ANY') { print "\n\n".'Found '.$match.' instances of "'.$string.'" in file "'.$logs{$log}.'"'; }
if($verbose | $string ne 'ANY') { print "\n\nMatch Case: ".($case ? 'TRUE' : 'FALSE')."\nTailing log: ".($tail ? $lines.' lines' : 'FALSE')."\nExact Match: ".($pattern eq $string ? 'FALSE' : 'TRUE')."\n\n"; }
print "\n";