Click here to Skip to main content
Click here to Skip to main content

Monitor your website performance and uptime with Perl

By , 3 Aug 2004
 

Sample Image - backlog.gif

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                 |
#!/usr/bin/perl
use warnings;
use strict;
use Tie::File;
use Net::SMTP;
use LWP::UserAgent;

#################################################################
#             Program  Settings
#
my $error_log  = 'Responser_errors.txt';# File to store errors of program
my $input_file = 'urls.txt';       # From where program will read WEB Addresses
my $smtp_file  = 'SMTP_Settings.txt';   # File for SMTP Settings
my $response_limit = 12; #In Seconds    # Positively diggit -> SendMail;
                                        #        0 -> will not send mail
my $send_mail  = 1;                # my $send_mail  = 1; ->SMTP option is ON,
                                   # my $send_mail  = 0; ->SMTP option is OFF
##################################################################
#                      END OF SETTINGS
# Do not edit bellow if you dont understand it.
##################################################################
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 /^#/;
   #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 .. $#all_addr) {
 chop $all_addr[$_] if ($all_addr[$_] =~ /\s+$/);
 next if ($all_addr[$_]  eq "");
 if ($all_addr[$_] =~ /^http:\/\/\S+\.\w{2,4}$/) {  
      #address will beginnig with http://,next some string
      # finish with point and 2 to 4 letters
   check_url($all_addr[$_]);    #call subroutine check_url()
 } 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;  # How match DOWN + WRONG Sites have
$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");
# Begin Compare mail message
my $msg = <<__END_OF_MAIL__;
To: $recipient
Subject: $err_num Error Sites | $localtime .
$localtime
$err

__END_OF_MAIL__
# End Compare

 $smtp->mail("$reverse_path") 
       or error("Failed to specify a reverse-path");#  If all is OK
 $smtp->to($recipient) 
       or error("Failed to specify a recipient");   #  that will
 $smtp->data([$msg]) 
       or error("Failed to send a message");     #  send mail
 $smtp->quit or error("Failed to quit");         #  to You
} else {
  print "Send Mail is OFF\n" if $err_num; # If you do not wish to receive mail
}

close OUT or error("Unable to close file $output_file");
print "\nProcess FINISH\n";

sub check_url {  # subroutine who check given 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');          #Accept HTML Page
        # send request
        my $start = time;      # Start timer
        my $res = $ua->request($req);
        # check the outcome
        if ($res->is_success) {
        # Success....all content of page has been received
          my $time = time;     # End timer
          my $out_format;
          $time = ($time - $start); # Result of timer
          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; # write to file
          print $out_format;     # print to console
        } else { # Error .... Site is DOWN and script send e-mail to you..
          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; # write to file
          print $out_format;     # print to console
    }
}
sub error {      # subroutine who print in Error Log
  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

About the Author

aa2max
United States United States
Member
Live in Michigan, USA

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionURL status is downmemberMember 473212918 Mar '12 - 23:39 
Hi ,
Thanks for this wonderful script.
unfortunately, the sub check_url { # subroutine who check given URL) is not giving the required output, as it is showing DOWN (even gmail, facebook).
Could it be related to FIREWALL setting., or some change in code is required.
I have tested it on my system (Windows 7) and on LINUX machine.
ajay

AnswerSMTP Authentication patchmemberadx44216 Feb '12 - 2:20 
The SMTP server I use (outbound.mailhop.org) requires authentication. I've added an authentication section to Responser in my deployment. Here's what you need:
 
1) Assuming Ubuntu 10.04 x64 (my environment).
2) Install the Perl Authen::SASL module. On Ubuntu,
sudo cpan Authen::SASL
3) Change the following line as shown:
my ($smtp_host,$recipient,$reverse_path,@all_addr) = ();
 
becomes
 
my ($smtp_host,$recipient,$reverse_path,$auth_user,$auth_pass, @all_addr) = ();
 
4) Change the following block as shown:
 
$smtp_host     = $2 if ($1 eq 'SMTPHost');
   $recipient     = $2 if ($1 eq 'Recipient');
   $reverse_path  = $2 if ($1 eq 'Reverse');
 
Becomes
 
$smtp_host     = $2 if ($1 eq 'SMTPHost');
   $auth_user     = $2 if ($1 eq 'User');
   $auth_pass     = $2 if ($1 eq 'Pass');
   $recipient     = $2 if ($1 eq 'Recipient');
   $reverse_path  = $2 if ($1 eq 'Reverse');
 
5) Edit your SMTP_Settings.txt and add the following fields to it:
 
User = 'yourSMTPuserName'

Pass = 'yourSMTPpassword'

 
6) Done! You should be able to authenticate against your SMTP server at this point.
Questionsend email notification for a specific error message appearing on the websitemembermohankz27 Apr '09 - 21:21 
Hi,
 
The script is really useful for administrating a site.
But I need to customize it for us.
 
I'm new to Perl and just started working on this.
I need to create a perl script which sends notificaton email for a specific error message which appeans when a website is accessed.
 
The thing is that the web site is loaded correctly with the whole content of the page but with an error sometimes. I've to send the notification if this specific error message appears while accessing the URL. Can you please suggest a way out for this or some reference/s etc.?
 
Thanks in anticipation.
 
Regards,
MohanZ
Generalquerystring value in urlmembersankarmca1 Nov '06 - 18:08 
hi
your script shows an error msg as 'wrong url' while querysting value is appended in the url. tell me how should i validate url in your script.
 
Sankar
GeneralMonitor Script does not send alert emailmembersonny227 Jan '06 - 11:20 
Hi
this Monitor script does not email
I need to have a password and user for smtp
its not safe to leave your mail server open without
a password at least.
 
is there a way to set this up to use localhost sendmail or qmail?
 
Thanks Sonny
GeneralCouple ideasmemberdmoses18 Apr '04 - 7:11 
Hi,
 
I like your project, simple yet effective.
 
Couple ideas:
 
a) Maybe add "use Time::HiRes qw ( time );" as a drop in replacement for the time function. Since many sites load in 1 - 3 seconds, maybe a higher resolution would be nice. If you do this I would move the 2nd time call to directly after the http request. I always like to use timers like this 1) get time 2) minimal op's required 3) get time. Not that the 'if' statement takes any real length of time, but its nice to be as accurate as possible..why not.
 
b) Your project inspired me to create my own. Rather than a logfile I just insert the time of day, and response time into a SQL database. I then used another page to query the database and graph it. Although this requires a database and graphing software, there are free ones available. It's nice to have a visual representation of the trends. Also putting the data into a database, allows for all kinds of processing, and statistics to be run against it. For Example what is the avg for a day/week/month, what is the longest wait, what is the average of the highest 5%, etc.
 
Cheers, nice work!
GeneralRe: Couple ideassussAnonymous26 Sep '05 - 17:36 
I'm inclined to agree with dmoses. the measure of time it takes for the response is far too granular to be of any real value.
 
Also, I would recommend that you check the list no more than 10 times each cycle that the script runs instead of a single check. What this will do is provide you with greater entropy from which to derive a true messue of site performance. Conditions that exist at the time of one request, may not exist at another, so with time between requests, you can more accurately judge the performance.
Generalthoughts...memberl a u r e n7 Apr '04 - 10:32 
interesting idea but surely...
 
what if the delay is ur link to the net rather than ur server?
how can it email me if its truly down?
 
are issues that need to be addressed no?
 
nice idea tho as i said
Smile | :)
 

"there is no spoon"
biz stuff   about me
GeneralRe: thoughts...membervander257 Apr '04 - 11:04 
Well there are 2 checks going on, it will email you if it is down, as in 404, or no connection. And it will also email you if the response time is greater than x. So as long as the connection you are running the script from is okay, then you will get an email if it is really down.
 
Smile | :)
 
-Mike
 
www.aspcontentmanagement.com
GeneralRe: thoughts...memberl a u r e n7 Apr '04 - 11:11 
is this your product?
 
so ur saying the mail server could be outside of ur webserver
ok that works
Smile | :)
 

"there is no spoon"
biz stuff   about me

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 4 Aug 2004
Article Copyright 2004 by aa2max
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid