#!/usr/bin/perl -w # my $mail = '/bin/mail'; use strict; sub probe { use Socket; use IO::Select; my ($host,$port,$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); my $response = ''; my $rh_set = IO::Select->select($read_set,undef,undef,$timeout); if ($rh_set) { read($s,$response,12); } #read($s,$response,12); #print $s ''; close($s); my $state = "down"; if ($response =~ m@\d\.\d+\.\d+@) { $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 action { my ($path,$state) = @_; if (-r "$path/$state.sh") { system("sh $path/$state.sh"); } } 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); } my $host = shift || 'localhost'; my $port = shift || 3306; my $timeout = shift || 3; my $state_path = shift || "."; my $email = shift; my $state_file = "$state_path/$host-$port-mysql.state"; my ($last_time,$last_state) = load_state($state_file); #print "$last_time,$last_state\n"; my ($time,$state) = probe($host,$port,$timeout); if ($last_state ne $state) { if ($email) { alert($email,"mysql://$host:$port",$last_time,$last_state,$time,$state); } action($state_path,$state); } save_state($state_file,$time,$state);