Rob
Rob

Reputation: 8101

Is there a way to check if a host is up?

I'm trying to do this in PHP. I need to check if a specified host is "up"

I thought of pinging the specified host (though I'm not sure how I would, since that would require root. --help here?)

I also though of using fsockopen() to try to connect on a specified port, but that would fail too, if the host wasn't listening for connections on that port.

Additionally, some hosts block ping requests, so how might I get around this? This part isn't a necessity, though, so don't worry about this too much. I realize this one might get tricky.

Upvotes: 1

Views: 11737

Answers (6)

Krzysiu
Krzysiu

Reputation: 172

There's no universal way to check it, but for most cases ping would work.

The problems with some proposals

  • exec might be not available in some shared hostings and as high level, third party function, it's slow and OS-depended
  • curl and HTTP based methods will work only if there's host with HTTP service on port 80, which might be not the case (I use it to check local machines for Samba connectivity)

When you may expect wrong results?

As I said, it will work in most cases, but it's not a silver bullet. You can do something with the first three cases, but not with the last.

  • your machine's firewall or network settings forbids sending pings (but then exec('ping… won't help)
  • your PHP installation is missing Sockets extension (which is also the biggest drawback of this way)
  • machine answer's too slow (which can be changed by tweaking $msTimeout parameter)
  • remote machine blocks all ICMP traffic (or just pings)

The code

function isHostUp($host, $msTimeout = 1000) {
    $socket  = socket_create(AF_INET, SOCK_RAW, 1);
    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 0, 'usec' => 1000 * $msTimeout));
    socket_connect($socket, $host, null);
    socket_send($socket, "\x08\x00\x7d\x4b\x00\x00\x00\x00PingHost", 16, 0);
    $result = (bool)@socket_read($socket, 255);
    socket_close($socket);
    return $result;
}

Usage/explanation

The usage is very simple, this function returns boolean value for given hostname or IP (as string), while the second parameter (integer) is optional and sets timeout in miliseconds. Default is 1000 ms, which is 1 s.

0 timeout means "no timeout" (wait as long as it's needed). At least that's what my experiments show, but I don't see it in PHP docs, so I wouldn't rely on that.

Example use:

isHostUp('1.1.1.1'); // simply check if 1.1.1.1 is reachable
isHostUp('example.com', 5000); // check if example.com is up and wait at most 5 seconds for reply

It works by pinging the machine, but unlike typical ping it doesn't check how quick the reply is, but if there's reply at all. If the machine is unreachable, it would produce warning on the line with socket_read, hence the silencing @ symbol.

Upvotes: 0

Ioan Cristian Barbu
Ioan Cristian Barbu

Reputation: 1

I used gethostbyname($hostname).

The function gives you the IP if the host is up, or the input hostname if it couldn't find the IP.

if ($hostname !== gethostbyname($hostname)) {
    //Host is up
}

Upvotes: -2

Paul McMillan
Paul McMillan

Reputation: 20107

The short answer is that there is no good, universal way to do this. Ping is about as close as you can get (almost all hosts will respond to that), but as you observed, in PHP that usually requires root access to use the low port.

Does your host allow you to execute system calls, so you could run the ping command at the OS level and then parse the results? This is probably your best bet.

$result = exec("ping -c 2 google.com");

If a host is blocking a ping request, you could do a more general portscan to look for other open ports (but this is pretty rude, don't do it to hosts who haven't given you specific permission). Nmap is a good tool for doing this. It uses quite a few tricks to figure out if a host is up and what services may or may not be running. Be careful though, as some shared hosting providers will terminate your account for "hacking activity" if you install and use Nmap, especially against hosts you do not control or have permission to probe.

Beyond that, if you are on the same unswitched ethernet layer as another host (if you happen to be on the same open WiFi network, for example), an ethernet adaptor in promiscuous mode can sniff traffic to and from a host even if it does not respond directly to you.

Upvotes: 4

Jeff Busby
Jeff Busby

Reputation: 2011

You could use cURL

$url = 'yoururl';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (200==$retcode) {
    // All's well
} else {
    // not so much
}

Upvotes: 1

user336242
user336242

Reputation:

For the host to be monitored at all, at least one port must be open. Is the host a web server? If so you could just open a connection to port 80, as long as it's opened successfully then at least some part of the host is working.

A better solution would be to have a script that is web accessible to just your monitor, and then you could open a connection to that, and that script would return various bits of system info.

EDIT--

How thorough do you want this test to be? [server on] -> [apache running] -> [web application working] Are all different levels of working. Just showing apache is returning something does at least show the server is on, but not that your web app is running. (I realise that you may not be running anything like this but I hope it's a useful example)

EDIT--

Would it be worth installing a lightweight http server (I mean very light weight) just for monitoring?

Failing that could you install something on the hosts that phoned home every so often to show they are up?

Upvotes: 0

buley
buley

Reputation: 29208

I typically do a simple cURL for a public page and see if it returns a 200. If you get a 500, 404, or anything besides a 200 response you know something fishy is up.

Upvotes: 5

Related Questions