#!/usr/bin/perl 
#
#
## Name:         check_pservers.pl - proxy monitoring program
#
## Author:      Tom Northcutt
## Synopsis:    Checks status of various proxy servers
## Description:
#               This script is designed to check the status of
#		various proxy servers and restart them if they
#		have stopped.

# user defined section #####

## HTTP PROXY SERVER CONFIGURATION:
# process name in a ps -C listing
$http_name = "squid"; 
#stop command
my $http_stop = "/etc/init.d/squid stop";
#start command
my $http_start = "/etc/init.d/squid start";

## OTHER PROXY SERVERS (ftp proxy, etc.)
# can be set up here 
# $other_name = "";
# my $other_stop = "";
# my $other_start = "";


# email address of person to receive homepage change warnings
#my $admin_email = q"root@localhost";
my $admin_email = q(sysadmin@mailserver.localdomain);


# sendmail
my $sendmail = "/usr/lib/sendmail -t";

# end user defined section #####

use Sys::Syslog qw(:DEFAULT setlogsock);
setlogsock "UNIX";

my $used_attempts = 0;
my %start = ();
$start{"$http_name"} = $http_start;
$start{"$other_name"} = $other_start;



## MAIN LOOP ####

##my @proxy  = ($http_name, $other_name);
my @proxy  = ($http_name);

foreach $proxy(@proxy){
  $used_attempts = 0;
  unless (&is_running("$proxy")){
    #we have a down process
    &restart($proxy, 3);
  }
}
1;

## SUBROUTINES ###


##(is_running PROCESS_NAME)
# Given a process name, this routine checks to see if a process
# is currently running.  If the process is up, the pid is 
# returned, otherwise 0.
sub is_running {
  my ($process_name) = @_;

  my @ps_info = `/bin/ps -C $process_name`;
  $null = shift(@ps_info); #first line is ps header info
  my $ps_elem = @ps_info; #num elements in @it #icky perl
  
  my $ps_line = $ps_info[--$ps_elem];
  $ps_line =~ s/^ +//; #ps output varies, remove all leading whitespace

  #in case server forked, process last line 
  my ($pid, @null) = split(/ /, $ps_line);
  return $pid if $pid;
  return 0;
  
}

## (restart PROCESS_NAME, ATTEMPTS)
# Attempts to restart the server specified by PROCESS_NAME.  
# This process will try to restart a problematic server ATTEMPTS 
# times unless a running server is detected.  
sub restart {
  my $proxy = shift;
  my $attempts = shift;

  if ($attempts == 0){     
    unless(&is_running("$proxy")){
      #print error message to syslog
      openlog('check_pservers', 'cons,pid', 'user');
      syslog("notice", "proxy $proxy down, could not be restarted");
      closelog();

      #send error to admin
      mail_admin("PSERVER_ERROR: proxy $proxy down, could not be restarted",
		 "After $used_attempts attempts, the proxy server $proxy could\
                  not be successfully restarted with the command:\
                  $start{$proxy}");
      return 0;
    }

  }elsif(&is_running("$proxy")){  
    my $rval = &is_running("$proxy");
    print "proxy $proxy restarted with pid $rval\n";
    openlog('check_pservers', 'cons,pid', 'user');
    syslog("notice", "proxy $proxy down, restarted with pid $rval");
    closelog();
    

    #send error to admin
    mail_admin("PSERVER_NOTICE: proxy $proxy down,restarted with pid $rval ",
	       "After $used_attempts attempts, the proxy server $proxy was 
                successfully restarted with the command:\
                $start{$proxy}");
    

    return $rval;

  }else{ #still down w/ more attempts
    system("$start{$proxy}");
    $used_attempts++;
    $attempts--;

    sleep(30); #give it time to either stabilize or die
    &restart($proxy, $attempts); #recursive test
  }
}


## (mail_admin SUBJECT, MESSAGE)
# Send a message to the system administrator leting them know of
# special circumstances. 
sub mail_admin {
  my ($subject,$message) = @_;
  
  open(MAIL, "| $sendmail")
    or die "PROXY-ALERT: Can't fork for sendmail: $!\n";
  
  print MAIL <<"ENDMAIL";
From: $admin_email
To: $admin_email
Subject: $subject

$message
ENDMAIL
  
   close(MAIL);		# close the pipe

}


=head1 NAME

check_pservers.pl - proxy monitoring program

=head1 AUTHOR

Tom Northcutt


=head1 SYNOPSIS

Checks status of various proxy servers


=head1 DESCRIPTION

This script is designed to check the status of
various proxy servers and restart them if they
have stopped.


=head1 SUBROUTINES

=item B<sub is_running(PROCESS_NAME)>

 Given a process name, this routine checks to see if a process
 is currently running.  If the process is up, the pid is 
 returned, otherwise 0.

=item B<sub restart(PROCESS_NAME, ATTEMPTS)>

 Attempts to restart the server specified by PROCESS_NAME.  
 This process will try to restart a problematic server ATTEMPTS 
 times unless a running server is detected.  

=item B<sub mail_admin(SUBJECT, MESSAGE)>

 Send a message to the system administrator leting them know of
 special circumstances. 

=cut


