Question

I'm looking for a PHP script that can be run as a cron job on my web host. It needs to run through a list of websites and check to make sure that each returns the Http response 200 OK. If a site doesn't return that response, or isn't available, it needs to send off an email to the website admin.

Was it helpful?

Solution

I've since refined this script to check to see if your website/webserver is still up and running. I've improved the error handling slightly and added a comfort email to let you know that the script is running successfully.

The comfort email relies on another file called healthcheck.txt to store some values until the script is run the next time. If it doesn't get automatically created, just create a 0 bytes text file, upload it and set the correct file permissions on it (read/write).

<?php
// set email server parameters
ini_set('sendmail_from', 'server.status@host.example.com' );
ini_set('SMTP', '127.0.0.1' );
ini_set('smtp_port', '25' );

ini_set('allow_url_fopen', true); //enable fopen

// define list of webservers to check
$webservers = array('www.example.com', 'www.example2.com');

function sendemail($subject,$message) // email function using standard php mail
{
$wrapmessage = wordwrap($message,70,"\n",true); // mail function can't support a message more than 70 characters per line
$to = 'you@example.com'; // who to send the emails to
// Headers ensure a properly formatted email
$headers = 'From: server.status@host.example.com' . "\r\n" .
    'Reply-To: server.status@host.example.com' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

return mail($to, $subject, $wrapmessage, $headers); //send the email
}

function getresponse($url) //queries a url and provides the header returned and header response
{
$ch = curl_init(); // create cURL handle (ch)
if (!$ch) { // send an email if curl can't initialise
    $subject = "Web Server Checking Script Error";
    $message = "The web server checking script issued an error when it tried to process ".$url.". Curl did not initialise correctly and issued the error - ".curl_error($ch)." The script has died and not completed any more tasks.";
    sendemail($subject,$message);
    die();
}
// set some cURL options
$ret = curl_setopt($ch, CURLOPT_URL, "http://".$url."/");
$ret = curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);   
$ret = curl_setopt($ch, CURLOPT_HEADER, true);
$ret = curl_setopt($ch, CURLOPT_NOBODY, true);
$ret = curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$ret = curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
$ret = curl_setopt($ch, CURLOPT_TIMEOUT, 30);

// execute
$ret = curl_exec($ch);

if (empty($ret)) {
    // some kind of an error happened
    $subject = "Web Server Checking Script Error";
    $message = "The web server checking script issued an error when it tried to process ".$url.". Curl was trying to execute and issued the error - ".curl_error($ch)." Further URLs will be tried.";
    sendemail($subject,$message);
    curl_close($ch); // close cURL handler
    } else {
        $info = curl_getinfo($ch); //get header info - output is an array
        curl_close($ch); // close cURL handler

        if (empty($info['http_code'])) {
                $subject = "Web Server Checking Script Error";
                $message = "The web server checking script issued an error when it tried to process ".$url."\r\nNo HTTP code was returned";
                sendemail($subject,$message);
        } else {
            // load the HTTP code descriptions
            $http_codes = parse_ini_file("/server/path/to/http-response-codes.ini");

            // results - code number and description
            $result = $info['http_code'] . " " . $http_codes[$info['http_code']];
        return $result; // $result contained a code, so return it
        }
    return None; //$info was empty so return nothing
    }
return None; // $ret was empty so return nothing
}

// this bit of code initiates the checking of the web server
foreach ($webservers as $webserver) { //loop through the array of webservers
    $status = getresponse($webserver); //get the status of the webserver
        if (empty($status)) {
        // nothing happens here because if $status is empty, the function returned nothing and an email was already sent.
        } else {
            if (strstr($status, "200")) { //search for the error code that means everything is ok
            // If found, don't do anything, just process the next one
            } else {
                $timestamp = date("m/d/Y H:i:s a", time()); //get the current date and time
                $error = $webserver." - ".$status." status error detected"; //set error message with server and response code
                $message = "At - ".$timestamp." - a http response error was detected on ".$webserver.".\r\nInstead of a 200 OK response, the server returned ".$status."\r\nThis requires immediate attention!"; //At what time was an error detected on which server and what was the error message
                sendemail($error,$message); //trigger the sendemail function
            }
        }
}

// Health Check. Comfort email twice a day to show script is actually running.
$healthfile = "/server/path/to/healthcheck.txt"; // path with the name of the file to store array data
$hfsize = filesize($healthfile); // filesize of healthcheck file
$notify = "16:00"; // specify the earliest time in the day to send the email - cron job settings dictate how close you'll get to this
$datenow = date("d-m-Y"); //what is current date as of now

if (file_exists($healthfile) && $hfsize !== 0) { //read contents of array from file if it exists and has data, otherwise create array with some defaults
    $valuestor = unserialize(file_get_contents($healthfile));
    } else { // file doesn't exist so we'll create an array with some defaults
    $valuestor = array("email_sent"=>0, "sent_date"=>$datenow, "iterations"=>0);
}
$i = $valuestor['iterations']; //get the iterations number from the valuestor array
$curdate = strtotime($datenow); //convert current date to seconds for comparison
$stordate = strtotime($valuestor['sent_date']); //convert stored date to seconds
if ($valuestor['email_sent'] == 1) { // has the email already been sent today
    if ($curdate == $stordate) { // if it has, is the current date equal to the stored date
        $i++; // yes it is, just increment the iterations
    } else { // it's a new day, reset the array
        $timestamp = date("m/d/Y H:i:s a", time()); //get the current date and time
        $subject = "Web Server Checking Script Health Status"; //set email subject line
        $message = "Message created: ".$timestamp."\r\nThe Web Server Checking script ran successfully for ".$i." time(s) on the ".$valuestor['sent_date']; //email message
        sendemail($subject,$message); //trigger the sendemail function
        $valuestor['email_sent'] = 0; // set email sent to false
        $valuestor['sent_date'] = $datenow; // set email send date to today
        $i = 1; // this is the first time the script has run today, so reset i to 1. It gets written to the array later.
        // echo $message;
    }
} else { // email has not been sent today
    $checktime = strtotime($notify); //convert $notify time (for current date) into seconds since the epoch
    if (time() >= $checktime) { // are we at or have we gone past checktime
        $i++; // increase the number of script iterations by 1
        $timestamp = date("m/d/Y H:i:s a", time()); //get the current date and time
        $subject = "Web Server Checking Script Health Status"; //set email subject line
        $message = "Message created: ".$timestamp."\r\nThe Web Server Checking script has successfully run and completed ".$i." time(s) today."; //email message
        sendemail($subject,$message); //trigger the sendemail function
        $valuestor['email_sent'] = 1; // set array to show that email has gone
        // echo $message;
    } else { // we haven't reached the check time yet
    $i++; // just increment the iterations
    }
}
$valuestor['iterations'] = $i; // update the array with the iterations number

// save the array to the file again
$fp = fopen($healthfile, 'w+'); // open or create the file, clear its contents and write to it
if (!$fp) { // handle the error with an email if the file won't open
$subject = "Web Server Checking Script Error";
$message = "The web server checking script issued an error when trying to open or create the file ".$healthfile." The script was ended without any new information being stored.";
sendemail($subject,$message);
} else {
fwrite($fp, serialize($valuestor)); // write to the file and serialise the array valuestor
fclose($fp); // close the file connection
} 
die(); // make sure that script dies and cron job terminates
?>

OTHER TIPS

I found it took me a while to research a good answer to this question. So for the benefit of the community, here's what I came up with after research on Stackoverflow and other forums.

You need two files for this to work. The PHP script that you execute via cron and a ini file that contains detailed descriptions of what the http response codes mean.

I hope this is of use to others.

server-check.php

<?php
// set email server parameters
ini_set('sendmail_from', 'server.status@host.example.com' );
ini_set('SMTP', '127.0.0.1' );
ini_set('smtp_port', '25' );

// define list of webservers to check
$webservers = array('www.example.com', 'www.example2.com');

function sendemail($subject,$message) // email function using standard php mail
{
$wrapmessage = wordwrap($message,70,"\n",true); // mail function can't support a message more than 70 characters per line
$to = 'you@example.com'; // who to send the emails to
// Headers ensure a properly formatted email
$headers = 'From: server.status@host.example.com' . "\r\n" .
    'Reply-To: server.status@host.example.com' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

return mail($to, $subject, $wrapmessage, $headers); //send the email
}

function getresponse($url) //queries a url and provides the header returned and header response
{
$ch = curl_init(); // create cURL handle (ch)
if (!$ch) {
    $subject = "Web Server Checking Script Error";
    $message = "The web server checking script issued an error when it tried to process ".$url."\r\nCouldn't initialize a cURL handle";
    sendemail($subject,$message);
    die();
}
// set some cURL options
$ret = curl_setopt($ch, CURLOPT_URL, "http://".$url."/");
$ret = curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);   
$ret = curl_setopt($ch, CURLOPT_HEADER, true);
$ret = curl_setopt($ch, CURLOPT_NOBODY, true);
$ret = curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$ret = curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
$ret = curl_setopt($ch, CURLOPT_TIMEOUT, 30);

// execute
$ret = curl_exec($ch);

if (empty($ret)) {
    // some kind of an error happened
    $subject = "Web Server Checking Script Error";
    $message = "The web server checking script issued an error when it tried to process ".$url."\r\ncurl_error ".$ch;
    sendemail($subject,$message);
    curl_close($ch); // close cURL handler
    die();
    } else {
        $info = curl_getinfo($ch);
        curl_close($ch); // close cURL handler

        if (empty($info['http_code'])) {
                $subject = "Web Server Checking Script Error";
                $message = "The web server checking script issued an error when it tried to process ".$url."\r\nNo HTTP code was returned";
                sendemail($subject,$message);
                die(); 
        } else {
            // load the HTTP codes
            $http_codes = parse_ini_file("/server/path/to/http-response-codes.ini");

            // results
            $result = $info['http_code'] . " " . $http_codes[$info['http_code']];
        }

    }
return $result;
}

foreach ($webservers as $webserver) { //loop through the array of webservers
    $status = getresponse($webserver); //get the status of the webserver
        if (strstr($status, "200")) { //search for the error code that means everythings ok
        return None; // Don't do anything, just process the next one
        } else {
        $timestamp = date("m/d/Y H:i:s a", time()); //get the current date and time
        $error = $webserver." - ".$status." status error detected"; //set error message with server and response code
        $message = "At - ".$timestamp." - a http response error was detected on ".$webserver.".\r\nInstead of a 200 OK response, the server returned ".$status."\r\nThis requires immediate attention!"; //At what time was an error detected on which server and what was the error message
        sendemail($error,$message); //trigger the sendemail function
        }
}
?>

http-response-codes.ini

[Informational 1xx]
100="Continue"
101="Switching Protocols"

[Successful 2xx]
200="OK"
201="Created"
202="Accepted"
203="Non-Authoritative Information"
204="No Content"
205="Reset Content"
206="Partial Content"

[Redirection 3xx]
300="Multiple Choices"
301="Moved Permanently"
302="Found"
303="See Other"
304="Not Modified"
305="Use Proxy"
306="(Unused)"
307="Temporary Redirect"

[Client Error 4xx]
400="Bad Request"
401="Unauthorized"
402="Payment Required"
403="Forbidden"
404="Not Found"
405="Method Not Allowed"
406="Not Acceptable"
407="Proxy Authentication Required"
408="Request Timeout"
409="Conflict"
410="Gone"
411="Length Required"
412="Precondition Failed"
413="Request Entity Too Large"
414="Request-URI Too Long"
415="Unsupported Media Type"
416="Requested Range Not Satisfiable"
417="Expectation Failed"

[Server Error 5xx]
500="Internal Server Error"
501="Not Implemented"
502="Bad Gateway"
503="Service Unavailable"
504="Gateway Timeout"
505="HTTP Version Not Supported"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top