Skip to content

Instantly share code, notes, and snippets.

@zyphlar
Created January 26, 2012 02:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zyphlar/1680682 to your computer and use it in GitHub Desktop.
Save zyphlar/1680682 to your computer and use it in GitHub Desktop.
Nagios PHP querier
<?php
// nag.php by Will Bradley, www.zyphon.com/arduino-nagios
// Script to parse Nagios status.dat and present it in simplified HTML.
// Also grabs graph images from /pnp4nagios if you edit pnp4nagios' apache.conf to not require authentication.
//
// Based on statusXML.php by Jason Antman
//
// +----------------------------------------------------------------------+
// | PHP EMS Tools http://www.php-ems-tools.com |
// +----------------------------------------------------------------------+
// | Copyright (c) 2006, 2007 Jason Antman. |
// | |
// | This program is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU General Public License as published by |
// | the Free Software Foundation; either version 3 of the License, or |
// | (at your option) any later version. |
// | |
// | This program is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU General Public License for more details. |
// | |
// | You should have received a copy of the GNU General Public License |
// | along with this program; if not, write to: |
// | |
// | Free Software Foundation, Inc. |
// | 59 Temple Place - Suite 330 |
// | Boston, MA 02111-1307, USA. |
// +----------------------------------------------------------------------+
// | Authors: Jason Antman <jason@jasonantman.com> |
// +----------------------------------------------------------------------+
// $Id: statusXML.php,v 1.6 2009/02/07 03:32:14 jantman Exp $
// $Source: /usr/local/cvsroot/admin-portal/nagios/statusXML.php,v $
$statusFile = "/var/cache/nagios3/status.dat";
$nag_version = getFileVersion($statusFile); // returns integer 2 or 3
$created_ts = 0;
$debug = false;
if($nag_version == 3)
{
$data = getData3($statusFile); // returns an array
}
else
{
$data = getData2($statusFile); // returns an array
}
$hosts = $data['hosts'];
$services = $data['services'];
$program = "";
if(array_key_exists("program", $data))
{
$program = $data['program'];
}
echo outputHTML($hosts, $services, $program);
function outputHTML($hosts, $services, $program)
{
if($_GET["minimal"] == "1") {
$minimal = true;
}
$ret = "";
// begin outputting XML
//header("Content-type: text/xml");
if($minimal){
$ret .= "$";
}
else {
$ret .= "<html>"."\n";
$ret .= '<head><style type="text/css">body { background-color: #fff; font:15px arial,sans-serif; } table {margin: 10px auto; } th { text-align: left; } .OK { background-color: green; } .WARNING { background-color: yellow; } .CRITICAL { background-color: red; } .perf { color: #666; font-size: 0.7em; padding-left: 50px; } </style></head>'."\n";
$ret .= "<body>"."<table>\n";
}
// program status
/*
if($program != "")
{
$ret .= '<programStatus>'."\n";
foreach($program as $key => $val)
{
$key = xmlname($key);
$val = xmlstring($val);
$ret .= ' <'.$key.'>'.$val.'</'.$key.'>'."\n";
}
$ret .= '</programStatus>'."\n";
}
*/
// hosts
foreach($hosts as $hostName => $hostArray)
{
if($minimal) {
$ret .= $hostArray['current_state'];
}
else {
$ret .= "<tr>";
$ret .= "<th>".$hostArray['host_name']."</th>";
switch($hostArray['current_state']) {
case 0:
$hoststate = "OK";
break;
case 1:
$hoststate = "WARNING";
break;
case 2:
$hoststate = "CRITICAL";
break;
}
$ret .= "<td class='".$hoststate."'>";
$ret .= $hoststate;
$ret .= "</td>";
$ret .= "<td class='perf'>".$hostArray['plugin_output']."</td>";
$hostgraphurl = "/pnp4nagios/image?host=".$hostArray['host_name']."&srv=_HOST_&view=1&source=0&start=".(time()-(60*60*24))."&end=".time();
$ret .= "<td class='graph'><a href='".$hostgraphurl."'><img width='199' height='25' src='".$hostgraphurl."' /></a></td>";
$ret .= "</tr>";
}
/*
$current_state = $hostArray['current_state'];
$ret .= ' <host>'."\n";
foreach($hostArray as $key => $val)
{
$key = xmlname($key);
$val = xmlstring($val);
$ret .= ' <'.$key.'>'.$val.'</'.$key.'>'."\n";
}
$ret .= ' </host>'."\n";
*/
}
// loop through the services
foreach ($services as $hostName => $service)
{
foreach ($service as $serviceDesc => $serviceArray)
{
if($minimal) {
$ret .= $serviceArray['current_state'];
}
else {
$ret .= "<tr>";
$ret .= "<th>".$serviceArray['host_name']." ".$serviceArray['service_description']."</th>";
switch($serviceArray['current_state']) {
case 0:
$servstate = "OK";
break;
case 1:
$servstate = "WARNING";
break;
case 2:
$servstate = "CRITICAL";
break;
}
$ret .= "<td class='".$servstate."'>";
$ret .= $servstate;
$ret .= "</td>";
$ret .= "<td class='perf'>".$serviceArray['plugin_output']."</td>";
$ret .= "</tr>";
}
}
}
if(!$minimal){
$ret .= "</table></body></html>";
}
return $ret;
}
// replace reserved characters in key for name
function xmlname($s)
{
$s = str_replace("<", "&lt;", $s);
$s = str_replace(">", "&gt;", $s);
$s = str_replace("&", "&amp;", $s);
return $s;
}
function xmlstring($s)
{
$s = str_replace("<", "&lt;", $s);
$s = str_replace(">", "&gt;", $s);
$s = str_replace("&", "&amp;", $s);
return $s;
}
// figure out what version the file is
function getFileVersion($statusFile)
{
global $created_ts;
$version = 2;
$fh = fopen($statusFile, 'r');
$inInfo = false;
while($line = fgets($fh))
{
if(trim($line) == "info {")
{
$inInfo = true;
}
elseif(trim($line) == "}")
{
$inInfo = false;
break;
}
if($inInfo)
{
$vals = explode("=", $line);
if(trim($vals[0]) == "created")
{
$created = $vals[1];
}
elseif(trim($vals[0]) == "version")
{
if(substr($vals[1], 0, 1) == "3")
{
$version = 3;
}
}
}
}
return $version;
}
// parse nagios2 status.dat
function getData2($statusFile)
{
// the keys to get from host status:
$host_keys = array('host_name', 'has_been_checked', 'check_execution_time', 'check_latency', 'check_type', 'current_state', 'current_attempt', 'state_type', 'last_state_change', 'last_time_up', 'last_time_down', 'last_time_unreachable', 'last_notification', 'next_notification', 'no_more_notifications', 'current_notification_number', 'notifications_enabled', 'problem_has_been_acknowledged', 'acknowledgement_type', 'active_checks_enabled', 'passive_checks_enabled', 'last_update');
// keys to get from service status:
$service_keys = array('host_name', 'service_description', 'has_been_checked', 'check_execution_time', 'check_latency', 'current_state', 'state_type', 'last_state_change', 'last_time_ok', 'last_time_warning', 'last_time_unknown', 'last_time_critical', 'plugin_output', 'last_check', 'notifications_enabled', 'active_checks_enabled', 'passive_checks_enabled', 'problem_has_been_acknowledged', 'acknowledgement_type', 'last_update', 'is_flapping');
# open the file
$fh = fopen($statusFile, 'r');
# variables to keep state
$inSection = false;
$sectionType = "";
$lineNum = 0;
$sectionData = array();
$hostStatus = array();
$serviceStatus = array();
#variables for total hosts and services
$typeTotals = array();
# loop through the file
while($line = fgets($fh))
{
$lineNum++; // increment counter of line number, mainly for debugging
$line = trim($line); // strip whitespace
if($line == ""){ continue;} // ignore blank line
if(substr($line, 0, 1) == "#"){ continue;} // ignore comment
// ok, now we need to deal with the sections
if(! $inSection)
{
// we're not currently in a section, but are looking to start one
if(strstr($line, " ") && (substr($line, -1) == "{")) // space and ending with {, so it's a section header
{
$sectionType = substr($line, 0, strpos($line, " ")); // first word on line is type
$inSection = true;
// we're now in a section
$sectionData = array();
// increment the counter for this sectionType
if(isset($typeTotals[$sectionType])){$typeTotals[$sectionType]=$typeTotals[$sectionType]+1;}else{$typeTotals[$sectionType]=1;}
}
}
if($inSection && $line == "}") // closing a section
{
if($sectionType == "service")
{
$serviceStatus[$sectionData['host_name']][$sectionData['service_description']] = $sectionData;
}
if($sectionType == "host")
{
$hostStatus[$sectionData["host_name"]] = $sectionData;
}
$inSection = false;
$sectionType = "";
continue;
}
else
{
// we're currently in a section, and this line is part of it
$lineKey = substr($line, 0, strpos($line, "="));
$lineVal = substr($line, strpos($line, "=")+1);
// add to the array as appropriate
if($sectionType == "service")
{
if(in_array($lineKey, $service_keys))
{
$sectionData[$lineKey] = $lineVal;
}
}
elseif($sectionType == "host")
{
if(in_array($lineKey, $host_keys))
{
$sectionData[$lineKey] = $lineVal;
}
}
// else continue on, ignore this section, don't save anything
}
}
fclose($fh);
$retArray = array("hosts" => $hostStatus, "services" => $serviceStatus);
return $retArray;
}
// parse nagios3 status.dat
function getData3($statusFile)
{
global $debug;
// the keys to get from host status:
$host_keys = array('host_name', 'modified_attributes', 'check_command', 'check_period', 'notification_period', 'check_interval', 'retry_interval', 'event_handler', 'has_been_checked', 'should_be_scheduled', 'check_execution_time', 'check_latency', 'check_type', 'current_state', 'last_hard_state', 'last_event_id', 'current_event_id', 'current_problem_id', 'last_problem_id', 'plugin_output', 'long_plugin_output', 'performance_data', 'last_check', 'next_check', 'check_options', 'current_attempt', 'max_attempts', 'state_type', 'last_state_change', 'last_hard_state_change', 'last_time_up', 'last_time_down', 'last_time_unreachable', 'last_notification', 'next_notification', 'no_more_notifications', 'current_notification_number', 'current_notification_id', 'notifications_enabled', 'problem_has_been_acknowledged', 'acknowledgement_type', 'active_checks_enabled', 'passive_checks_enabled', 'event_handler_enabled', 'flap_detection_enabled', 'failure_prediction_enabled', 'process_performance_data', 'obsess_over_host', 'last_update', 'is_flapping', 'percent_state_change', 'scheduled_downtime_depth');
// keys to get from service status:
$service_keys = array('host_name', 'service_description', 'modified_attributes', 'check_command', 'check_period', 'notification_period', 'check_interval', 'retry_interval', 'event_handler', 'has_been_checked', 'should_be_scheduled', 'check_execution_time', 'check_latency', 'check_type', 'current_state', 'last_hard_state', 'last_event_id', 'current_event_id', 'current_problem_id', 'last_problem_id', 'current_attempt', 'max_attempts', 'state_type', 'last_state_change', 'last_hard_state_change', 'last_time_ok', 'last_time_warning', 'last_time_unknown', 'last_time_critical', 'plugin_output', 'long_plugin_output', 'performance_data', 'last_check', 'next_check', 'check_options', 'current_notification_number', 'current_notification_id', 'last_notification', 'next_notification', 'no_more_notifications', 'notifications_enabled', 'active_checks_enabled', 'passive_checks_enabled', 'event_handler_enabled', 'problem_has_been_acknowledged', 'acknowledgement_type', 'flap_detection_enabled', 'failure_prediction_enabled', 'process_performance_data', 'obsess_over_service', 'last_update', 'is_flapping', 'percent_state_change', 'scheduled_downtime_depth');
# open the file
$fh = fopen($statusFile, 'r');
# variables to keep state
$inSection = false;
$sectionType = "";
$lineNum = 0;
$sectionData = array();
$hostStatus = array();
$serviceStatus = array();
$programStatus = array();
#variables for total hosts and services
$typeTotals = array();
# loop through the file
while($line = fgets($fh))
{
$lineNum++; // increment counter of line number, mainly for debugging
$line = trim($line); // strip whitespace
if($line == ""){ continue;} // ignore blank line
if(substr($line, 0, 1) == "#"){ continue;} // ignore comment
// ok, now we need to deal with the sections
if(! $inSection)
{
// we're not currently in a section, but are looking to start one
if(substr($line, strlen($line)-1, 1) == "{") // space and ending with {, so it's a section header
{
$sectionType = substr($line, 0, strpos($line, " ")); // first word on line is type
$inSection = true;
// we're now in a section
$sectionData = array();
// increment the counter for this sectionType
if(isset($typeTotals[$sectionType])){$typeTotals[$sectionType]=$typeTotals[$sectionType]+1;}else{$typeTotals[$sectionType]=1;}
}
}
elseif($inSection && trim($line) == "}") // closing a section
{
if($sectionType == "servicestatus")
{
$serviceStatus[$sectionData['host_name']][$sectionData['service_description']] = $sectionData;
}
elseif($sectionType == "hoststatus")
{
$hostStatus[$sectionData["host_name"]] = $sectionData;
}
elseif($sectionType == "programstatus")
{
$programStatus = $sectionData;
}
$inSection = false;
$sectionType = "";
continue;
}
else
{
// we're currently in a section, and this line is part of it
$lineKey = substr($line, 0, strpos($line, "="));
$lineVal = substr($line, strpos($line, "=")+1);
// add to the array as appropriate
if($sectionType == "servicestatus" || $sectionType == "hoststatus" || $sectionType == "programstatus")
{
if($debug){ echo "LINE ".$lineNum.": lineKey=".$lineKey."= lineVal=".$lineVal."=\n";}
$sectionData[$lineKey] = $lineVal;
}
// else continue on, ignore this section, don't save anything
}
}
fclose($fh);
$retArray = array("hosts" => $hostStatus, "services" => $serviceStatus, "program" => $programStatus);
return $retArray;
}
// this formats the age of a check in seconds into a nice textual description
function ageString($seconds)
{
$age = "";
if($seconds > 86400)
{
$days = (int)($seconds / 86400);
$seconds = $seconds - ($days * 86400);
$age .= $days." days ";
}
if($seconds > 3600)
{
$hours = (int)($seconds / 3600);
$seconds = $seconds - ($hours * 3600);
$age .= $hours." hours ";
}
if($seconds > 60)
{
$minutes = (int)($seconds / 60);
$seconds = $seconds - ($minutes * 60);
$age .= $minutes." minutes ";
}
$age .= $seconds." seconds ";
return $age;
}
/*
// the keys to get from host status:
$host_keys = array('host_name', 'has_been_checked', 'check_execution_time', 'check_latency', 'check_type', 'current_state', 'current_attempt', 'state_type', 'last_state_change', 'last_time_up', 'last_time_down', 'last_time_unreachable', 'last_notification', 'next_notification', 'no_more_notifications', 'current_notification_number', 'notifications_enabled', 'problem_has_been_acknowledged', 'acknowledgement_type', 'active_checks_enabled', 'passive_checks_enabled', 'last_update');
// keys to get from service status:
$service_keys = array('host_name', 'service_description', 'has_been_checked', 'check_execution_time', 'check_latency', 'current_state', 'state_type', 'last_state_change', 'last_time_ok', 'last_time_warning', 'last_time_unknown', 'last_time_critical', 'plugin_output', 'last_check', 'notifications_enabled', 'active_checks_enabled', 'passive_checks_enabled', 'problem_has_been_acknowledged', 'acknowledgement_type', 'last_update', 'is_flapping');
*/
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment