Introduction
Be notified if your website is down or slow.
What It Does
This simple Perl script is designed to run on a schedule. If you are on Windows, you can use the Windows Task Scheduler, if you are on Linux, you can run schedule it as a Cron job. The script will check a website, actually "grab" the default page, then record how long this takes. You can then receive an email if the page is down, or if the response time is greater than what you have set.
How It Works
The script has 3 files:
- URLS.txt - This file holds all the URLs (websites) that you wish to check. Each URL is on one line. This makes it easy to update and change your list without having to dig into the Perl script.
- SMTP_Settings.txt - This file holds the SMTP settings that the script should use to send the notifications, as well as who to send it to. Again, these settings are located out of the script in a text file to make things easier to change.
- responser.pl - Is the script that does the task of checking the website and attempting to grab the default file. You do need to set your minimum response time that is acceptable to you within the script itself. Keep in mind that if the connection you are running the script from is slow, you may also hit your response time limit, thus triggering the email.
Other files created by the script:
The script will also create an error file, where any reported errors are written to. This is handy for troubleshooting, this file can be deleted at anytime.
The script will also create a daily log file each time it's run. The daily log file will append, so each day you'll have a record of what happened.
The complete script with the readme file can be downloaded for free from here.
Sample Output From the Log File
******************************************************
+--------------------------------------------------------------------------------+
| Time: 23:26:31 |
| HOST STATUS RESPONSE |
+--------------------------------------------------------------------------------+
| http://www.yahoo.com/ ACCESSED Response 1 seconds |
| http://www.hotmail.com/ ACCESSED Response 1 seconds |
| http://www.ebay.com/ ACCESSED Response 1 seconds |
| http://www.example.com/ ACCESSED Response 0 seconds |
| http://www.not/ a real site.com WRONG N/A |
+--------------------------------------------------------------------------------+
| Time: 23:30:17 |
| HOST STATUS RESPONSE |
+--------------------------------------------------------------------------------+
| http://www.yahoo.com/ ACCESSED Response 0 seconds |
| http://www.hotmail.com/ ACCESSED Response 0 seconds |
| http://www.ebay.com/ ACCESSED Response 1 seconds |
| http://www.example.com/ ACCESSED Response 0 seconds |
| http://www.not/ a real site.com WRONG N/A |
+--------------------------------------------------------------------------------+
| Time: 23:31:26 |
| HOST STATUS RESPONSE |
+--------------------------------------------------------------------------------+
| http://www.yahoo.com/ ACCESSED Response 0 seconds |
| http://www.hotmail.com/ ACCESSED Response 1 seconds |
| http://www.ebay.com/ ACCESSED Response 0 seconds |
| http://www.example.com/ ACCESSED Response 0 seconds |
| http://www.not/ a real site.com WRONG N/A |
use warnings;
use strict;
use Tie::File;
use Net::SMTP;
use LWP::UserAgent;
my $error_log = 'Responser_errors.txt';
my $input_file = 'urls.txt';
my $smtp_file = 'SMTP_Settings.txt';
my $response_limit = 12;
my $send_mail = 1;
die "File $input_file is not exist\n" unless (-e $input_file);
die "SMTP is ON, but file $smtp_file is not exist\n" unless (-e $smtp_file);
my $localtime = localtime;
our @errors;
my ($day,$month,$date,$hour,$year) = split /\s+/,scalar localtime;
my $output_file = 'report-'.$date.'.'.$month.'.'.$year.'.txt';
my ($smtp_host,$recipient,$reverse_path, @all_addr) = ();
tie @all_addr, 'Tie::File',
$input_file or error("Cant open $input_file to read addresses");
if (-e $output_file) {
open(OUT,">> $output_file")
or error("Cant open exist file $output_file for append");
} else {
open(OUT,"> $output_file")
or error("Cant open new file $output_file for writting");
}
my @smtp_settings;
if ($^O =~ /win/i) {
tie @smtp_settings, 'Tie::File', $smtp_file,,
recsep => "\012"
or error("Cant open $smtp_file to read SMTP settings");
} else {
tie @smtp_settings, 'Tie::File', $smtp_file,autochomp => '0'
or error("Cant open $smtp_file to read SMTP settings");
}
for (@smtp_settings) {
chomp;
next if /^
if (/^(\w+)\s=\s'(\S+)'/) {
$smtp_host = $2 if ($1 eq 'SMTPHost');
$recipient = $2 if ($1 eq 'Recipient');
$reverse_path = $2 if ($1 eq 'Reverse');
}
}
print OUT "\n+" .('-' x 84) . "+\n";
print OUT "|", ' ' x 30,"Time: $hour",' ' x 40,"|\n";
print OUT "|",' 'x 10,'HOST',' ' x 37,'STATUS',' ' x 7,
"RESPONSE |\n";
print OUT "+" .('-' x 84) . "+\n";
for (0 .. $
chop $all_addr[$_] if ($all_addr[$_] =~ /\s+$/);
next if ($all_addr[$_] eq "");
if ($all_addr[$_] =~ /^http:\/\/\S+\.\w{2,4}$/) {
check_url($all_addr[$_]);
} else {
my $out_format = sprintf "| %-50.50s %-10s %-20s|\n",
$all_addr[$_], "WRONG", "N/A";
printf OUT $out_format;
printf $out_format;
push @errors, "$all_addr[$_] is WRONG Address.";
}
}
my $err = join "\015\012",@errors;
my $err_num = scalar @errors;
$send_mail = 0 unless $err_num;
untie @all_addr or error("Unable to close file $input_file");
if ($send_mail) {
my $smtp = Net::SMTP->new($smtp_host,
-Debug=>1,
-Timeout=>20,
-Hello=>"$smtp_host")
or error("Cant connect to $smtp_host");
my $msg = <<__END_OF_MAIL__;
To: $recipient
Subject: $err_num Error Sites | $localtime .
$localtime
$err
__END_OF_MAIL__
$smtp->mail("$reverse_path")
or error("Failed to specify a reverse-path");
$smtp->to($recipient)
or error("Failed to specify a recipient");
$smtp->data([$msg])
or error("Failed to send a message");
$smtp->quit or error("Failed to quit");
} else {
print "Send Mail is OFF\n" if $err_num;
}
close OUT or error("Unable to close file $output_file");
print "\nProcess FINISH\n";
sub check_url {
my $target = $_[0];
my $ua = LWP::UserAgent->new;
$ua->agent("$0/0.1 " . $ua->agent);
my $req = HTTP::Request->new(GET => "$target");
$req->header('Accept' => 'text/html');
my $start = time;
my $res = $ua->request($req);
if ($res->is_success) {
my $time = time;
my $out_format;
$time = ($time - $start);
if ($response_limit && ($response_limit <= $time)) {
push(@errors, "Slow response from $target\: $time seconds");
$out_format = sprintf "| %-50.50s %-10s %-20s |\n",
$target, "SLOW", "Response $time seconds";
} else {
$out_format = sprintf "| %-50.50s %-10s %-20s |\n",
$target, "ACCESSED", "Response $time seconds";
}
print OUT $out_format;
print $out_format;
} else {
my $out_format = sprintf "| %-50.50s %-10s %-20s |\n",
$target, "DOWN", " N/A";
push(@errors, "$target is DOWN." . $res->status_line)
or error("Cannot push error for DOWN");
print OUT $out_format;
print $out_format;
}
}
sub error {
my $error_msg = shift;
open ERR,">> $error_log"
or die "Cannot open log file $error_log : $!\n";
print ERR "$localtime\: $error_msg : $!\n";
close ERR or die "Cannot close log file $error_log : $!\n";
}
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.
A list of licenses authors might use can be found here.