CURRENT CONFIGURATION: Windows 2003 Server x64, Perl
OBJECTIVE: Monitor ports and services inside data centre, send notification by email, keep statistics in log files
SOLUTION: I wrote monitor.pl scripts to check are services, network and Internet connections alive. The Perl script based on Jonathan Eisenzopf moniker.pl script. Configuration file is in csv format.
Monitor.pl script:
#!/usr/bin/perl
#
# Changed by Vadims Zenins http://vadimszenins.blogspot.com
# Date 28/03/2007 18:02
# Version 1.00
#
# This script based on idea
# moniker.pl - monitors named server ports
# by Jonathan Eisenzopf. v0.2 20000107
#
# Description: Script to monitor ports (services), send notification by email,
# keep statistics in log files
#
# 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 General Public License for more details.
#
# INCLUDES
use strict;
use Net::Telnet;
use Getopt::Std;
use Text::CSV_PP;
use Mail::Sender;
use Sys::HostIP;
use Sys::Hostname;
use Cwd;
use Archive::Zip;
use File::Find;
use File::Basename;
require "ctime.pl";
# CONSTANTS
my $timeout = 4;
my $emailsender = 'monitor@mycompany.com';
my $report_email = 'sysadmin@mycompany.com';
# Write Yours report folder name
my $report_folder = "reports";
# Write Your Reports type
my $report_file = "ServicesFaultReport";
# Write Your Reports file extension
my $report_file_ext = "csv";
# Write Your log name
my $log_folder = "logs";
my $log_temp = '_temp.txt';
# Write SMTP server addresse
my $serversmtp = 'smtp.mycompany.com';
# Write email subjects
my $email_alarm_subj = "Services Monitor Alarm";
my $email_warning_subj = "Services Monitor Warning";
my $email_report_subj = "Services Monitor Report";
# Write fault quantity for warning email
my $email_warning_quantity = 1;
# Write fault quantity for alert email (for data centre)
my $email_alarm_quantity = 3;
#******************** END of config ********************
my ($host, $service, $_ERR, $sock, $send_to_warning, $send_to_alarm);
my ($quantity_current, $conf_alarm_quantity, $conf_warning_quantity);
my ($listfile, $extensions, @files);
my ($tmp, $temp, @tmp);
my ($Date, $report_archive);
#my $report = ();
my $services = {
ftp => { port => 21, print => "", waitfor => '/220/' },
ssh => { port => 22, print => "", waitfor => '/SSH/' },
telnet => { port => 23, print => "", waitfor => '/(login|username)/' },
domain => { port => 42, print => "", waitfor => '' },
http => { port => 80, print => "HEAD / HTTP/1.0\n\n", waitfor => '/200/' },
https => { port => 443, print => "HEAD / HTTP/1.0\n\n", waitfor => '/200/' },
pop => { port => 110, print => "", waitfor => '/\+OK/' },
nntp => { port => 119, print => "", waitfor => '/200/' },
imap => { port => 143, print => "", waitfor => '/OK/' },
irc => { port => 6667, print => "", waitfor => '' },
smtp => { port => 25, print => "", waitfor => '/SMTP/' }
};
# MAIN
# get the command line arguments
my %opts = ();
getopt('hsef', \%opts);
##$service = $opts{s};
##$host = $opts{h};
##$send_to_warning = $opts{e} if exists $opts{e};
##$listfile = $opts{f} if exists $opts{f};
##print "Host: $host; Service: $service; Email: $send_to_warning\n";
&get_time();
my $myipaddress = hostip; # get (text) dotted-decimal ip
my $myhostname = hostname; # get hostname
# change email subjects
$email_alarm_subj = "Services Monitor Alarm from $myhostname";
$email_warning_subj = "Services Monitor Warning from $myhostname";
# --- Set final log file name ---
#--- replace / OR : with - in the string ---
($temp = $Date) =~ s/[\/:]/-/g;
#--- delete first space and all after one in the string ---
$temp =~ s/[" "].*//g;
#--- replace " " with , in the string ---
#$temp =~ s/[ ]/,/g;
my $finallog_name = "log-$myhostname-$temp.log";
print "finallog name: $finallog_name\n";
# --- Set report file name ---
#--- replace first / to - in the string ---
($temp = $Date) =~ s/[\/:]/-/o;
#--- delete first / and all after one in the string ---
$temp =~ s/\/.*//g;
my $log_archive = "log-$temp.zip";
$report_archive = "$report_file-$myhostname-$temp.zip";
my $report_file = "$report_file-$myhostname-$temp.$report_file_ext";
print "report_file name: $report_file\n";
# get working directory
my $current_dir = dirname($opts{f}) if (exists $opts{f}) ;
# change '\' to '/' (avoids trouble in substitution on Win2k)
$current_dir =~ s|\\|/|g;
#my $current_dir = getcwd; # get pathname of current working directory
print "Working dir: $current_dir\n";
$report_folder = "$current_dir/$report_folder";
$log_folder = "$current_dir/$log_folder";
# --- Check Log folder ---
&folder_check_create($log_folder);
print "log name: $log_folder/$log_temp\n";
# --- Delete old temporary log file ---
&dirfile_delete ($log_folder, $log_temp);
# --- Check report folder ---
&folder_check_create($report_folder);
# Check if Final log file exists, archive old if does not
if (-e "$log_folder/$finallog_name") {
print "Final log name: $log_folder/$finallog_name\n";;
} else {
&archive_reports($log_folder,"log",$log_archive,'move');
# my $finallog_exist = 0;
}
# Check if Report file exists, archive old if does not
if (-e "$report_folder/$report_file") {
# my $finallog_exist = 1;
print "File $report_folder/$report_file exists\n";
} else {
&archive_reports($report_folder,$report_file_ext,$report_archive,'move');
&send_mail ($report_folder, $report_archive, $serversmtp, $emailsender,
$report_email, '', "$email_report_subj $report_archive", ' ');
$tmp = "Number of consecutive failed requests,Date,Host,Service,Error,Monitor ip address,Monitor hostname\n";
&file_open_add_close($report_folder,$report_file,$tmp);
# my $reportfile_exist = 0;
}
# --- Start temporary log file ---
$tmp = "--- Start of programm on $myhostname ---\n";
&PrintAndWriteToLog($log_folder,$log_temp,$tmp);
# --- Check for file operators -f ---
$listfile = $opts{f} if exists $opts{f};
#$tmp = "Config filename (-f): $listfile\n";
#&PrintAndWriteToLog($log_folder,$log_temp,$tmp);
# --- if they passed us a filename ---
if (exists $opts{f} && -e $opts{f}) {
# --- create new Text::CSV object ---
my $csv = new Text::CSV_PP;
# --- open the file they specified ---
open(SERVERSFILE, "< $listfile")
or die "&PrintAndWriteToLog($log_folder,$log_temp,Cannot open file $listfile: $!\n)";
while () {
#--- skip the line if it's empty ---
next unless /\S+/;
#--- get the columns for the line ---
$csv->parse($_);
($host,$service,$send_to_warning,$conf_warning_quantity,
$send_to_alarm,$conf_alarm_quantity) = $csv->fields;
# $tmp = "Host: $host; Service: $service;
# send_to_warning: $send_to_warning; conf_warning_quantity: $conf_warning_quantity;
# send_to_alarm: $send_to_alarm; conf_alert_quantity: $conf_alarm_quantity\n";
# &PrintAndWriteToLog($log_folder,$log_temp,$tmp);
# overwrite email_*_quantity from config file
if ($email_warning_quantity != $conf_warning_quantity && 1 <= $conf_warning_quantity) {
$email_warning_quantity = $conf_warning_quantity };
if ($email_alarm_quantity != $conf_alarm_quantity && 1 <= $conf_alarm_quantity) {
$email_alarm_quantity = $conf_alarm_quantity };
# Check $email_warning_quantity > $email_alarm_quantity, bu should be <=
$email_warning_quantity = $email_alarm_quantity if $email_warning_quantity > $email_alarm_quantity;
# $tmp = "Host: $host; Service: $service;
# send_to_warning: $send_to_warning; warning_quantity: $email_warning_quantity;
# send_to_alarm: $send_to_alarm; alert_quantity: $email_alarm_quantity\n";
# &PrintAndWriteToLog($log_folder,$log_temp,$tmp);
next unless ($host =~ /\S+/ && $service =~ /\S+/);
#--- check the service and alert ---
&check_service_and_alarm($host,$service,$send_to_warning,$email_warning_quantity,$send_to_alarm,$email_alarm_quantity);
}
close(SERVERSFILE);
}
#else {
# &usage unless exists($opts{h}) && exists($opts{s});
#
# $service = $opts{s};
# $host = $opts{h};
# $send_to = $opts{e} if exists $opts{e};
# print "Host: $host; Service: $service; Email: $send_to\n";
#
# # check the service
# if (&check_service($host,$service)) {
# print "$host:$service is operational.\n";
# } else {
## &alert($send_to,$host,$service,$_ERR);
# print "$host:$service is NOT operational.\nError: $_ERR.\n";
# }
#}
$tmp = "--- End of programm. ---\n\n";
&PrintAndWriteToLog($log_folder,$log_temp,$tmp);
addfile1tofile2("$log_folder/$log_temp","$log_folder/$finallog_name");
### SUBROUTINES
#**** Archive reports *****
sub archive_reports {
my ($dir,$report_file_ext,$archive_name,$arcaction) = @_;
@files = ();
cwd $dir;
$extensions = $report_file_ext;
find(\&files_list_short, $dir);
$tmp = scalar @files;
$tmp = "Found $tmp $extensions file(s) for archiving\n";
&PrintAndWriteToLog($log_folder,$log_temp,$tmp);
if (@files <= 0) {
return 2;
} else {
my $zip = Archive::Zip->new();
my $zippath = "$dir/$archive_name";
# read-in the existing zip file if any
if (defined $zippath && -f $zippath) {
my $status = $zip->read($zippath);
warn "Read $zippath failed\n" if $status != "AZ_OK";
}
# add files
cwd $dir;
foreach my $memberName (@files) {
if (-d $memberName ){
warn "Can't add tree $memberName\n"
# if $zip->addFile( $memberName ) != "AZ_OK";
if $zip->addTree( $memberName, $memberName ) != "AZ_OK";
} else {
# print "dir,file: $dir, $memberName\n";
$zip->addFile( $memberName )
or &PrintAndWriteToLog($log_folder,$log_temp,"Can't add file $memberName\n");
}
}
# prepare the new zip path
my $newzipfile = genfilename();
my $newzippath = "$dir/$newzipfile";
# write the new zip file
my $status = $zip->writeToFileNamed($newzippath);
if ($status == "AZ_OK") {
# rename (and overwrite the old zip file if any)?
if (defined $zippath) {
my $res = rename $newzippath, $zippath;
if ($res) {
&PrintAndWriteToLog($log_folder,$log_temp,"Updated file $zippath\n");
} else {
&PrintAndWriteToLog($log_folder,$log_temp,"Created file $newzippath, failed to rename to $zippath\n");
}
} else {
&PrintAndWriteToLog($log_folder,$log_temp,"Created file $newzippath\n");
}
} else {
&PrintAndWriteToLog($log_folder,$log_temp,"Failed to create file $newzippath\n");
}
if ($arcaction eq 'move') {
# print " Moving to archive\n";
if (-e $zippath) {
foreach my $memberName (@files) {
&file_delete($memberName);
}
}
}
}
}
#**** list all files in folder *****
sub files_list_short {
#my ($dir, $extensions) = @_;
# print "directory: $File::Find::dir\nExtentions: $extensions\n";
my $filename = ();
if (/\.($extensions)$/) {
cwd $File::Find::dir;
return if -d $File::Find::name; # skip directories
# my $fileagedays = fileAgeDays($_);
# if ($fileagedays < $maxFileAgeDays) {
# printf STDERR "$File::Find::name (%.3g)\n"; #, $fileagedays;
(my $filename = $File::Find::name) =~ s/^[a-zA-Z]://; # remove the leading drive letter:
push @files, $filename;
print "$extensions file: $filename\n";
# push @files, "./$_";
# print "$extensions file: $_\n";
# }
return @files;
}
}
#**** Generate file name *****
sub genfilename {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
sprintf "%04d%02d%02d-%02d%02d%02d.zip", $year+1900, $mon+1, $mday, $hour, $min, $sec;
}
#**** Check folder *****
sub folder_check_create {
my ($temp) = @_;
if (-e $temp) {
print "Folder $temp already exists\n";
} else {
mkdir ($temp);
print "Folder $temp was created\n";
}
}
#**** get time *****
sub get_time() {
$Date = &ctime(time);
return $Date;
}
# ***** Send Mail *****
sub send_mail {
my ($dir,$file_name,$smtp,$emailsender,$send_to,$send_cc,$email_subj,@message) = @_;
# print "dir,file,to = @_ \n";
chdir("$dir");
open my $DEBUG, ">> $log_folder/$log_temp"
or die "Can't open the debug file: $!\n";
ref (my $sender = new Mail::Sender({from => $emailsender,
smtp => $smtp})) or die &PrintAndWriteToLog($log_folder,$log_temp,"$Mail::Sender::Error\n");
if ($send_to ne 0){
if ($file_name eq 'not_file')
{
ref ($sender->MailMsg(
{to => $send_to,
cc => $send_cc,
subject => $email_subj,
# debug => $DEBUG'
msg => "@message"
}));
$tmp = "Mail sent TO: $send_to CC: $send_cc without attachment\n";
&PrintAndWriteToLog($log_folder,$log_temp,$tmp);
} else {
ref ($sender->MailFile(
{to => $send_to,
cc => $send_cc,
subject => $email_subj,
msg => "@message",
file => $file_name }));
$tmp = "Mail sent TO: $send_to CC: $send_cc with attachment $file_name\n";
&PrintAndWriteToLog($log_folder,$log_temp,$tmp);
}
}
else {
$tmp = "! Dont sent to $send_to $Mail::Sender::Error\n";
&PrintAndWriteToLog($log_folder,$log_temp,$tmp);}
}
#***** Message print & write to log *****
sub PrintAndWriteToLog
{
my ($dir,$filename,$temp) = @_;
&get_time();
$temp = "$Date $temp";
print "$temp";
&file_open_add_close($dir,$filename,$temp);
}
# ***** Delete file if specified directory and file name *****
sub dirfile_delete {
my ($rdir, $filename) = @_;
$temp = "$rdir/$filename";
if (-e $temp) {
unlink($temp) ;
&PrintAndWriteToLog($log_folder,$log_temp,"Deleted File: $temp\n");
} else {
&PrintAndWriteToLog($log_folder,$log_temp,"can not delete file: $temp, because file does not exist\n");
}
}
# ***** Delete file if specified full file name *****
sub file_delete {
my ($temp) = @_;
if (-e $temp) {
unlink($temp) ;
&PrintAndWriteToLog($log_folder,$log_temp,"Deleted File: $temp\n");
} else {
&PrintAndWriteToLog($log_folder,$log_temp,"can not delete file: $temp, because file does not exist\n");
}
}
#***** Check the Service & Alert ******
sub check_service_and_alarm {
($host,$service,$send_to_warning,$email_warning_quantity,
$send_to_alarm,$email_alarm_quantity) = @_;
if (&check_service($host,$service)) {
$tmp = "$host:$service is operational.\n";
&PrintAndWriteToLog($log_folder,$log_temp,$tmp);
&dirfile_delete ($log_folder,"$host.$service") if (-e "$log_folder/$host.$service");
return 1;
} else {
&Check_repeating_of_error($log_folder,$host,$service,$email_warning_quantity,$email_alarm_quantity);
$_ERR = "$quantity_current,$_ERR";
# print "quantity_current:$quantity_current\n";
&PrintAndWriteToLog($log_folder,$log_temp,"quantity_current:$quantity_current\n");
&file_open_add_close($report_folder,$report_file,"$_ERR\n");
$tmp = "! $host:$service is NOT operational.
! Error:\n $_ERR
Test number is $quantity_current from $email_warning_quantity/$email_alarm_quantity\n";
&PrintAndWriteToLog($log_folder,$log_temp,$tmp);
my @message_warning = <<"END_MESSAGE";
This is a Warning email from $myhostname IP: $myipaddress
$host:$service is NOT operationalafter $quantity_current number(s) of consecutive failed requests.
Error is:
$_ERR
Regards,
Systems Administrator
END_MESSAGE
my @message_alarm = <<"END_MESSAGE";
! This is a ALARM message from $myhostname IP: $myipaddress
$host:$service is NOT operational after $quantity_current numbers of consecutive failed requests.
Error is:
$_ERR
Regards,
Systems Administrator
END_MESSAGE
if ($quantity_current >= $email_warning_quantity && $quantity_current < $email_alarm_quantity) {
&send_mail ($report_folder, 'not_file', $serversmtp, $emailsender,
$send_to_warning, '', $email_warning_subj, @message_warning);
} else {
# if ($quantity_current >= $email_alarm_quantity) {
&send_mail ($report_folder, 'not_file', $serversmtp, $emailsender,
$send_to_alarm, $send_to_warning, $email_alarm_subj, @message_alarm);
}
# &send_mail ($report_folder,'not_file',$serversmtp,$emailsender,$send_to_warning,$email_warning_subj,$tmp);
return 0;
}
}
#***** Check repeating of error ******
sub Check_repeating_of_error {
my ($dir,$file_name,$file_extension,$email_warning_quantity,$email_alarm_quantity) = @_;
if (-e ("$dir/$file_name.$file_extension")) {
# $temp = "File $dir/$file_name.$file_extension exists\n";
# &PrintAndWriteToLog($log_folder,$log_temp,"$temp");
&fault_file_replace("$dir/$file_name.$file_extension");
return $quantity_current;
} else {
# $temp = "File $dir/$file_name.$file_extension does not exist\n";
# &PrintAndWriteToLog($log_folder,$log_temp,"$temp\n");
&file_open_add_close($log_folder,"$host.$service",pack("A","1"));
$quantity_current = 1;
return $quantity_current;
}
}
#***** replase fault File *****
sub fault_file_replace {
my ($dir,$fault_file,$fault_file_ext) = @_;
open(FAULT_FILE, "< $dir/$fault_file.$fault_file_ext")
or die PrintAndWriteToLog("Couldn't open file $dir/$fault_file.$fault_file_ext: $!\n");
#sysopen(FAULT_FILE, "$dir/$fault_file.$fault_file_ext", "O_WRONLY|O_TRUNC")
# or die PrintAndWriteToLog("Couldn't open file: $!\n");
@tmp =;
close FAULT_FILE;
@tmp[0] =~ s/^\D//g;
$quantity_current = unpack("A",@tmp[0]);
#&PrintAndWriteToLog($log_folder,$log_temp,"quantity_old:$quantity_current\n");
$quantity_current = $quantity_current + 1;
#&PrintAndWriteToLog($log_folder,$log_temp,"quantity_current:$quantity_current\n");
open(FAULT_FILE, "> $dir/$fault_file.$fault_file_ext")
or die PrintAndWriteToLog("Couldn't open file $dir/$fault_file.$fault_file_ext: $!\n");
print FAULT_FILE pack("A","$quantity_current");
close FAULT_FILE;
return $quantity_current;
}
#***** Open or create, Add and Close Report File *****
sub file_open_add_close {
my ($report_folder,$report_file,@report) = @_;
#--- open report File ---
open(REPORT_FILE,">> $report_folder/$report_file");
#--- Add to Report File ---
print REPORT_FILE @report;
#--- Close Report File ---
close REPORT_FILE;
}
#***** Check Service ******
sub check_service {
($host,$service) = @_;
#--- make sure user specified a valid service ---
die &PrintAndWriteToLog($log_folder,$log_temp,"! Service $service does not compute.\n")
unless defined $services->{$service};
my $port = $services->{$service}->{port};
my $sock = new Net::Telnet (Telnetmode => 0);
my $waitfor = $services->{$service}->{waitfor};
#--- Create a connection to the remote host ---
eval {
$sock->open(Host => $host,
Port => $port,
Timeout => $timeout
);
};
#--- Catch any errors ---
if ($@) {
&get_time();
$_ERR = "$Date,$host,$service,Can not establish connection,$myipaddress,$myhostname";
return 0;
}
# send data to remote host
$sock->print($services->{$service}->{print}) if $services->{$service}->{print};
# wait for regex match
if (!($sock->waitfor($waitfor))) {
$_ERR = "$Date,$host,$service,Timed out waiting for $waitfor,$myipaddress,$myhostname";
return 0;
}
# things went well
return 1;
}
#*** Add File1 to File2 ****
sub addfile1tofile2 {
my ($file1, $file2) = @_;
open(IN,$file1) || die "cannot open $file1 for reading: $!";
open(OUT,">>$file2") || die "cannot create $file2: $!";
while () { #read line from $file1 to $_
print OUT $_; # write line $_ to file $file2
}
close(IN) || die "can't close $file1: $!";
close (OUT) || die "can't close $file2: $!";
}
sub usage {
die <
Usage: monitor -h host -s service [-e email]
monitor -f
DIE
}
1;
__END__
Configuration file:
#hostname/IP,service,send_to_warning,conf_warning_quantity,send_to_alarm,conf_alarm_quantity
myserver.mydomain.com,http,"sysadmin@mycompany.com",1,"notifications@mycompany.com",3
myserver.mydomain.com,smtp,"sysadmin@mycompany.com",1,"notifications@mycompany.com",4
12.12.12.12,ssh,"sysadmin@mycompany.com",1,"notifications@mycompany.com",5
www.mydomain.com,http,"sysadmin@mycompany.com",1,"notifications@mycompany.com",5
www.eircom.ie,http,"sysadmin@mycompany.com",1,"notifications@mycompany.com",3
home.btireland.ie,http,"sysadmin@mycompany.com",1,"notifications@mycompany.com",3
www.magnet.ie,http,"sysadmin@mycompany.com",1,"notifications@mycompany.com",3
11.11.11.11,http,"sysadmin@mycompany.com",1,"notifications@mycompany.com",3
ftp.mydomain.com,ftp,"sysadmin@mycompany.com",1,"notifications@mycompany.com",5
DOWNLOAD: monitor.zip
Download md5: 2f982b123f93926aeca5f521bacf7185
Комментариев нет:
Отправить комментарий