#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# 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 Library 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.
#
#################################################################
# Name : syslog-fifo.pl
# Summary : Syslog fifo script
# Author : Tony Green
# Date : Dec '00
# Synopsis : Syslog automation script
#################################################################
#
# Hash array to seperate messages into individual files
# To add a new entry use the following syntax
# "5th Column Title" => ".suffix of file"
# You will need to restart the script.
%suffix = (
"sendmail" => ".mail",
"sshd" => ".ssh",
"su" => ".auth",
"PAM_pwdb" => ".auth",
"cron" => ".cron",
"crond" => ".cron",
"vpop3d" => ".pop",
"named" => ".named",
"named-xfer" => ".named",
"nscd" => ".named",
"ftp" => ".ftp",
"ftpd" => ".ftp",
"generic" => ".messages",
"capacity" => ".capacity",
"housekeeping" => ".housekeeping",
"prtdiag" => ".prtdiag",
"savecore" => ".crash",
"snmpdx" => ".snmp",
"perfomance" => ".perf",
"disaster-recovery" => ".disaster",
"httpd" => ".apache"
);
%alerts = (
"portwatch" => 'suyash.j@net4.in',
"file system full" => 'nocbang@net4india.net',
);
my $id = 'syslog-fifo.pl';
my $pidfile = '/var/run/syslog-fifo.pid';
my $warn = 'suyash.j\@net4.in';
my $basedir = '/var/log';
my $fifo = "$basedir/messages.fifo";
my $bit = "$basedir/unknown.messages";
# Check if we are already running
if ( -f $pidfile )
{
open (PID,$pidfile) or die "Couldn't open $pidfile\n";
$oldpid = <PID>;
close (PID) or die "Couldn't close $pidfile\n";
open (PS,"ps -fp $oldpid|") or die "Couldn't open ps stream\n";
while (<PS>)
{
next if m/UID/;
die "$id seems to be running already (pid $oldpid)" if m/$id/;
}
close (PS);
unlink $pidfile;
}
open (PID,">$pidfile") or die "Couldn't write to $pidfile\n";
print PID $$;
close (PID) or die "Couldn't close $pidfile\n";
%months = (
"Jan" => "1",
"Feb" => "2",
"Mar" => "3",
"Apr" => "4",
"May" => "5",
"Jun" => "6",
"Jul" => "7",
"Aug" => "8",
"Sep" => "9",
"Oct" => "10",
"Nov" => "11",
"Dec" => "12"
);
if ( -e $fifo && -r $fifo )
{ die "$fifo is not a pipe\n" unless -p $fifo }
else
{ die "$fifo is not there\n" }
# Open the 'input stream' from the named pipe
open (FIFO, $fifo) || die "Couldn't open fifo file";
# Turn into a 'daemon'
while ( 1 == 1 )
{
# While we have lines in the named pipe do this loop
while ( <FIFO> )
{
next if m/last message repeated/;
next if m/pam_setcred/;
next if m/Cannot delete credentials/;
&checkline($_);
chomp ($_);
@line = split (/\ +/, $_);
# Try to ensure there is a valid line by matching the 'tag'
#next unless ( $line[4] =~ m/\w*:$/ && $line[4] =~ m/last/ );
# Specifiy the month field
$month = "$line[0]";
$monthtest = $months{$month};
if ( ! defined($monthtest))
{
# This isn't a valid line - dump
# it into the 'bit bucket'
open (BIT, $bit);
print BIT "$_\n";
close (BIT);
}
else
{
# Specifiy the host field
$host = "$line[3]";
$host =~ tr/[A-Z]/[a-z]/;
my $domain = $host;
$host =~ s/\..+//;
$domain =~ s/$host\.//;
if ($domain =~ m/$host/)
{ $domain = 'net4india.net'; }
# Specifiy the type field
$type = "$line[4]";
# Get rid of the colon from the type field
$type =~ s/://;
# Get rid of the pid from the type field
$type =~ s/\[.*\]//;
# Build up the directory for storing the log files
$dir = $basedir . "/" . $month;
# Create the logdir/month directory if its not already there
&createlogdir($dir);
# Build up the directory for storing the log files
$dir = $dir . "/" . $domain;
# Create the logdir/month directory if its not already there
&createlogdir($dir);
# Add the host onto the logdir variable
$dir = $dir . "/" . $host;
# Create the logdir/month/host directory if this not
already there
&createlogdir($dir);
# From the type variable, figure out if this line should
be split
# into a different file by trying to access the 'type'
# in the %suffix hash array
$filetype = $suffix{$type};
# If $filetype is not defined it means that it did not
find its
# 'type' in the hash array, therefore we want it in the
bit bucket
if ( ! defined($filetype))
{
$filetype = $suffix{generic};
}
# Build up the 'output' stream
$file = ">> " . $dir . "/" . $host . $filetype;
$basefile = $dir . "/" . $host . $filetype;
# Open the output stream, write the line and close it again.
#&checkfilesize($basefile);
open (OUTPUT, $file) || die "Could not open $file";
print OUTPUT "$_\n";
close (OUTPUT);
}
# Slow things down just a touch to ensure we get everything
# through from the named pipe before parsing it.
select(undef, undef, undef, 0.05);
}
# Since we got an EOF from the fifo, give it a few seconds and
# then try again.
# Only new lines will be written into the named pipe so we can
# happily just process what has been written into it
sleep 5;
}
# Close the fifo at the end of the script
close ( FIFO );
###############################################################################
# Sub routines
###############################################################################
# Create subdirectories
sub createlogdir
{
if ( ! -d $_[0] )
{
mkdir ($_[0], 0755) || die "Could not create $_[0]\n";
print "Creating $_[0]\n";
}
}
# Simple sub to email out important messages
sub checkline
{
my $line = shift;
foreach $key (keys(%alerts))
{
if ( $line =~ m/$key/i )
{
open (MAIL, "|mailto -s 'Found $key in syslog' $alerts{$key}")
|| die "Couldn't open mail stream";
print MAIL $_;
close (MAIL);
}
}
}
sub checkfilesize
{
my $file = $_[0];
my $size = (stat($file))[7];
if ( $size > 10000 ) { system('gzip $file'); }
}
No comments:
Post a Comment