#!/usr/bin/perl -w # use strict; my $mail = '/bin/mail'; sub probe { use Socket; use IO::Select; my ($host,$port,$uri,$timeout) = @_; my $proto = getprotobyname('tcp'); my $iaddr = inet_aton($host) or die "inet_aton: $!"; my $paddr = sockaddr_in($port,$iaddr); my $s; socket($s,PF_INET,SOCK_STREAM,$proto) or die "socket: $!"; connect($s,$paddr) or return "down"; my $read_set = new IO::Select(); $read_set->add($s); select($s); $| = 1; select(STDOUT); print $s "GET $uri HTTP/1.0\n"; print $s "Host: $host:$port\n"; print $s "\n"; my $response = ''; my $rh_set = IO::Select->select($read_set,undef,undef,$timeout); if ($rh_set) { $response = <$s>; } close($s); my $state = "down"; if ($response =~ m@HTTP/1.\d 200 OK@) { $state = "up"; } return (time(),$state); } sub load_state { my ($state_file) = @_; my $sf; my ($time,$state) = (0,"unknown"); open($sf,"<$state_file") or return ($time,$state); if (<$sf> =~ m/(\d+) (\w+)/) { $time = $1; $state = $2; } close($sf); return ($time,$state); } sub save_state { my ($state_file,$time,$state) = @_; my $sf; open($sf,">$state_file") or die "open: $!"; print $sf "$time $state"; close($sf); } sub alert { use POSIX qw(strftime); my ($email,$id,$last_time,$last_state,$time,$state) = @_; my $p; $time = strftime "%a %b %e %H:%M:%S %Y",localtime($time); open($p,"|$mail -s 'status changed $id $state' '$email'"); print $p "$id\n$state $time\n"; print $p "\n"; close($p); } sub action { my ($path,$state) = @_; if (-r "$path/$state.sh") { system("sh $path/$state.sh"); } } my $host = shift || 'localhost'; my $port = shift || 80; my $uri = shift || '/'; my $timeout = shift || 3; my $state_path = shift || "."; my $email = shift; my $state_file = "$state_path/$host-$port-http.state"; my ($last_time,$last_state) = load_state($state_file); #print "$last_time,$last_state\n"; my ($time,$state) = probe($host,$port,$uri,$timeout); if ($last_state ne $state) { if ($email) { alert($email,"http://$host:$port$uri",$last_time,$last_state,$time,$state); } action($state_path,$state); } save_state($state_file,$time,$state);