Page 1 of 1

class to check if servers are down

Posted: Sat Oct 21, 2006 9:11 pm
by s.dot
This following class will check X amount of servers to see if they can be pinged. If the ping request reports anything other than a 0% loss of packets, you will be emailed alerting you that that server may be down. You should set this on a shedule to run every X minutes.

I tested this on Windows. Whether or not it would work on a linux server, I don't know.

I'm going to configure mine to TXT my cell phone, but I figure i'd produce something useful while I was at it! So here it is:

The Code

Code: Select all

<?php

/* This class will check X amounts of servers to see if they can be pinged.
*  If they can't be pinged, or ping reports more than a 0% loss of packets, 
* you will be emailed.
*
* author: scottayy@gmail.com
*/

class serverup
{
	var $servers = array();
	var $output;
	
	//add a server ip to be tested
	//@param string $server_ip
	function add_server($server_ip)
	{
		$this->servers[] = $server_ip;
	}
	
	//check if up
	//@param string $email
	function check($email)
	{
		foreach($this->servers AS $server)
		{
			
			//check if output array is empty
			if(!empty($this->output))
			{
				$this->output = array();
			}
			
			//execute ping
			exec('ping '.$server, $this->output);
			
			//check the output
			if($percent_loss = $this->check_output())
			{
				if($percent_loss !== true)
				{
					$msg = 'Server '.$server.' may be down. Ping is reporting a '.$percent_loss.'% ' .
					'loss of packets on '.date("n-d-Y \a\\t g:i A").".\n";
				}
			} else
			{
				$msg = 'Server '.$server.' may be down.  Ping reports it to be unreachable on '.
				date("n-d-Y \a\\t g:i A").".\n";
			}
			
			//mail results if server may be down
			if(!empty($msg))
			{
				mail($email, $subject='Server May Be Down', $msg);
			}
		}
	}
	
	//checks ping result for % of lost pings
	function check_output()
	{
		$output = implode("\n", $this->output);
		if(preg_match("/([\d]{1,3})% loss/", $output, $matches))
		{
			if($matches[1] > 0)
			{
				return $matches[1];
			} else
			{
				return true;
			}
		} else
		{
			return false;
		}
	}
}
The Test

Code: Select all

$serverup = new serverup();
$serverup->add_server('1.1.1.1');
$serverup->add_server('1.1.1.1.1.1.1');
$serverup->check('you@email.com');
The Output (emails that it sent)

Code: Select all

Server 1.1.1.1 may be down. Ping is reporting a 100% loss of packets on 10-22-2006 at 11:09 PM.

Code: Select all

Server 1.1.1.1.1.1.1 may be down.  Ping reports it to be unreachable on 10-22-2006 at 11:09 PM.

Posted: Sat Oct 21, 2006 10:12 pm
by s.dot
Wow, sending the output to a text message on your phone is easy!

I just replace my email in

Code: Select all

$serverup->check('you@email.com');
with

Code: Select all

$serverup->check('0123456789@cwemail.com');
That's how it's done for centennial. For most cell phone carriers its yournumber@somedomain.com.

Now I will get txt msg alerts when my server goes down! sooooooo cool 8)

Posted: Sat Oct 21, 2006 10:31 pm
by Ambush Commander
I was thinking the next thing you could do was eliminate the system call using a native PHP implementation of ping. PEAR's got something like that.

If the server does go down, I wonder whether or not you'd like to be constantly be annoyed by text messages every (insert interval you're running script here).

You may also choose to regard this as a bug, although it won't manifest: if the computer running the script is disconnected from the Internet, it will report it incorrectly down. Of course, you won't get an email since it's not connected either.

Posted: Sat Oct 21, 2006 10:41 pm
by s.dot
Ambush Commander wrote:I was thinking the next thing you could do was eliminate the system call using a native PHP implementation of ping. PEAR's got something like that.
Cool, I'll look into that.
Ambush Commander wrote:If the server does go down, I wonder whether or not you'd like to be constantly be annoyed by text messages every (insert interval you're running script here).
Heck yes :P time = $$
Ambush Commander wrote:You may also choose to regard this as a bug, although it won't manifest: if the computer running the script is disconnected from the Internet, it will report it incorrectly down. Of course, you won't get an email since it's not connected either.
Very true.

Posted: Tue Oct 24, 2006 4:45 pm
by s.dot
Alright, so, I have this running on my PC every 10 minutes.

The task is..

C:\php\php.exe C:\Apache2\htdocs\tasks\serverup.class.php

Every 10 minutes the command prompt window pops up while it's completing. Takes about 30 seconds, and it pops up on top of everything. Is there a way to run this in "silent" mode. Or at least have it minimized while it's running?

Posted: Tue Oct 24, 2006 4:52 pm
by Luke
that's so cool!

Posted: Tue Oct 24, 2006 4:52 pm
by Chris Corbyn
scottayy wrote:Alright, so, I have this running on my PC every 10 minutes.

The task is..

C:\php\php.exe C:\Apache2\htdocs\tasks\serverup.class.php

Every 10 minutes the command prompt window pops up while it's completing. Takes about 30 seconds, and it pops up on top of everything. Is there a way to run this in "silent" mode. Or at least have it minimized while it's running?
Maybe something like:

Code: Select all

<?php

set_time_limit(0);
ignore_user_abort();

echo "Dude -- Kill the browser, it's fine!";
flush();

do {
    $serverup = new serverup();
    $serverup->add_server('1.1.1.1');
    $serverup->add_server('1.1.1.1.1.1.1');
    $serverup->check('you@email.com');
    sleep(60 * 10);
} while (true);

?>
Open it in FF, wait for that text to appear, kill the window and see if it keep going. Technically it should do :)

Posted: Tue Oct 24, 2006 5:07 pm
by Ambush Commander
Set "Run as" to "NT AUTHORITY\SYSTEM"

Posted: Tue Oct 24, 2006 7:30 pm
by s.dot
Ambush Commander wrote:Set "Run as" to "NT AUTHORITY\SYSTEM"
worked like a charm.

Posted: Wed Oct 25, 2006 4:52 am
by Mordred
If the computer running the script is disconnected from the Internet, it will report it incorrectly down.
If pinging google doesn't work, assume the local internet connection is down ;) Of course this is better achieved by pinging a collection of servers and checking if at least one of them is reachable.

Posted: Wed Oct 25, 2006 5:48 am
by Chris Corbyn
Mordred wrote:
If the computer running the script is disconnected from the Internet, it will report it incorrectly down.
If pinging google doesn't work, assume the local internet connection is down ;) Of course this is better achieved by pinging a collection of servers and checking if at least one of them is reachable.
The way you check if it's a network issue with heartbeat (and I guess it applies generally) is like this (you need two machines within distance of getting a cable between them). Just connect a serial cable between the two machines. Check for life over the serial connection. If that's alive try it over the eth0 connection. If eth0 doesn't respond, but serial does something's up with the local network.

Posted: Wed Oct 25, 2006 6:11 am
by Mordred
This will only work for a really "local" connection ;)
What about if your ISP, or the router in your building is down? You need to check connectivity with machines which are several hops from you. But still, pinging the first two hops can really help in checking if it's the connectivity problem is on the local or on the remote site.
Actually that's what traceroute is for, so it might be better to include a stripped down traceroute report if the pings fail.

Posted: Wed Oct 25, 2006 6:35 am
by timvw
Makes me wonder why we have SNMP...

Posted: Wed Oct 25, 2006 10:18 am
by Weirdan
Ambush Commander wrote:I was thinking the next thing you could do was eliminate the system call using a native PHP implementation of ping. PEAR's got something like that.
There's no such thing as php ping implementation, and I doubt it would ever be done for strictly technical reasons: ping requires root permissions, and php interpreter usually don't have them.

Posted: Wed Oct 25, 2006 6:26 pm
by Ambush Commander
Oh, I see, the PEAR class simply wraps the ping call so that it works across platforms. Still, it's probably a better idea to use Network_Ping for portability.