Я написал (хорошо собранный из кода других людей) очень простой монитор работоспособности для наших серверов - это всего лишь монитор ICMP (ping), и он очень хорошо работает для нашего ограниченного количества серверов (около 20),и очень быстроВот код (реальные функции проверки пинга, я думаю, основаны на работе Бирка Дженсена (http://birk -jensen.dk / 2010/09 / php-ping / ), и я только что использовал его функцииотображать зеленый кружок PNG, когда все в порядке, и красные для каждого сервера, который не работает (если есть).
<html>
<head>
<style type='text/css'>
*{
font-family:verdana,tahoma,arial;
font-size:17px;
}
.light{width:30px;}
h1{
font-size:25px;
}
</style>
<meta http-equiv="refresh" content="30">
</head>
<body>
<?php
$time1=date('H:i:s');
echo "Last Refresh Time = $time1<br/><hr/>";
error_reporting(0);
/*-----------------------------------------------------------------------------------------*/
// Checksum calculation function
function icmpChecksum($data)
{
if (strlen($data)%2)
$data .= "\x00";
$bit = unpack('n*', $data);
$sum = array_sum($bit);
while ($sum >> 16)
$sum = ($sum >> 16) + ($sum & 0xffff);
return pack('n*', ~$sum);
}
/*-----------------------------------------------------------------------------------------*/
function PingTry1($pingaddress){
// Making the package
$type= "\x08";
$code= "\x00";
$checksum= "\x00\x00";
$identifier = "\x00\x00";
$seqNumber = "\x00\x00";
$data= "testing123";
$package = $type.$code.$checksum.$identifier.$seqNumber.$data;
$checksum = icmpChecksum($package); // Calculate the checksum
$package = $type.$code.$checksum.$identifier.$seqNumber.$data;
// And off to the sockets
$socket = socket_create(AF_INET, SOCK_RAW, 1);
socket_set_option ( $socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>1, "usec"=>0) );
socket_connect($socket, $pingaddress, null);
$startTime = microtime(true);
socket_send($socket, $package, strLen($package), 0);
if (socket_read($socket, 255)) {
return true;
}
else{
return false;
}
socket_close($socket);
}
/*-----------------------------------------------------------------------------------------*/
function DoTheCheck($name,$ip){
global $errors;
global $j;
if (PingTry1($ip)==1){
//do nothing
}else{
$j++;
$errors[$j] = "$name --> $ip";
}
}
/*-----------------------------------------------------------------------------------------*/
//READ IN THE INI FILE INTO $filedata Array
$myFile1="hosts.ini";
$filehandle1 = fopen($myFile1, 'r') or die("Couldn't open file [$myFile1]");
$number1=count(file($myFile1));;
$filedata = fread($filehandle1, filesize($myFile1));
fclose($filehandle1);
// Create an array with each line of the file
$array1 = explode("\r\n", $filedata);
unset($filedata); //free up a bit of memory
foreach ($array1 as &$line) { // step through the array, line by line
if (!empty($line)){
list ($name,$ip)=split(",",$line);
DoTheCheck($name,$ip);
}
}
if ($errors){
echo 'The Following Hosts are down - <br/><br/><table>';
foreach ($errors as &$value) {
$k++;
echo '<tr><td><img class="light" src="red.png" /></td><td>'.$errors[$k].'</td></tr>';
}
echo '</tr></table>';
}
else{echo '<img class="light" src="green.png" /><h1>ALL IPS ARE UP!</h1>';}
?>
</body>
</html>
Приведенный выше код отлично работает для серверов, но, похоже, не работает вообще дляКоммутаторы Cisco - вероятно, что-то связанное с тем, как они «пингуют» как таковые.
Я давно не работал над этим сценарием из-за обязательств колледжа и т. Д., Но я вернулся к выполнениюстолько исследований Google, сколько я могу, но, по общему признанию, я в лучшем случае PHP n00b уровня 2 или 3. Сегодня я нашел пару решений, которые работают для коммутаторов, но у них есть периоды ожидания 5 или 6 секунд, что недопустимо, поскольку яхочу, чтобы система зациклилась как можно больше и как можно более чисто, и записала время простоя для последующего построения графика.
Например - я пробовал это:
function ping($host, $timeout = 1) {
/* ICMP ping packet with a pre-calculated checksum */
$package = "\x08\x00\x7d\x4b\x00\x00\x00\x00PingHost";
$socket = socket_create(AF_INET, SOCK_RAW, 1);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $timeout, 'usec' => 0));
socket_connect($socket, $host, null);
$ts = microtime(true);
socket_send($socket, $package, strLen($package), 0);
if (socket_read($socket, 255))
$result = microtime(true) - $ts;
else $result = false;
socket_close($socket);
return $result;
}
, а также это:
$url = '192.168.1.1';
$socket = ( bool )false;
$error = ( bool )false;
$socket = @fsockopen( $url, 23, $errno, $errstr, 1 ) or $error = ( bool )true;
if ( ( $socket ) && ( !$error ) )
{
echo "bound";
/* socket is bound - do something */
}
else
{
echo "not bound , [$errstr]";
/* socket is dead - errors are in $errno & $errstr */
}
if ($socket)fclose($socket);
И они оба, кажется, работают, когда хост находится в сети, но если я дам ему IP, который не существует (для тестирования, как если бы хост был в автономном режиме), потребуется около 5 или более секунд для тайм-аутаодин IP, который слишком медленный для моих нужд.
Можно ли сделать это, используя pcntl_fork или даже curl с многопоточностью?или несколько вызовов 'exec' или даже AJAX (я готов попробовать что-нибудь на этом этапе)
или какой-то код уровня данных (уровень 2). Сканирование на Mac также было бы неплохо - я не ожидаюлюбой, кто напишет полный код, но я уверен, что кто-то, кто делал подобные вещи раньше, мог бы иметь представление о подводных камнях и о том, как их обойти.
Итак, в целом - просто и легкоИсправление было бы неплохо (я буду продолжать мечтать :-D), но любая помощь или совет очень ценятся.
РЕДАКТИРОВАТЬ - после некоторого совета попробовать Net_Ping в PEAR, я получил следующий код:
<?php
$time1=date('H:i:s');
echo "Last Refresh Time = $time1<br/><hr/>";
//not sure if still needed - error_reporting(0);
require_once "Net/Ping.php";
$ping = Net_Ping::factory();
$ping->setArgs(array('count' => 2, 'ttl' => 50, 'timeout' => 1));
/*---------------------------------------------------------------------*/
function DoPing($ip)
{
global $ping;
$results = $ping->ping($ip);
if ($results->_loss==0) {return true;}else{return false;}
}
/*---------------------------------------------------------------------------------*/
function DoTheCheck($name,$ip){
global $errors;
global $j;
if (DoPing($ip)==1){
//do nothing
}else{
$j++;
$errors[$j] = "$name --> $ip";
}
}
/*-----------------------------------------------------------------------------------*/
//READ IN THE INI FILE INTO $filedata Array
$myFile1="hosts.ini";
$filehandle1 = fopen($myFile1, 'r') or die("Couldn't open file [$myFile1]");
$number1=count(file($myFile1));;
$filedata = fread($filehandle1, filesize($myFile1));
fclose($filehandle1);
// Create an array with each line of the file
$array1 = explode("\r\n", $filedata);
unset($filedata); //free up a bit of memory
foreach ($array1 as &$line) { // step through the array, line by line
if ( (!empty($line)) && (!strstr($line,'##')) ) {
list ($name,$ip)=split(",",$line);
DoTheCheck($name,$ip);
}
}
if ($errors){
echo 'The Following Hosts are down - <br/><br/><table>';
foreach ($errors as &$value) {
$k++;
echo '<tr><td><img class="light" src="red.png" /></td><td>'.$errors[$k].'</td></tr>';
}
echo '</tr></table>';
}
else{echo '<img class="light" src="green.png" /><h1>ALL IPS ARE UP!</h1>';}
?>
но это слишком медленно ... требуется около минуты или двух, чтобы проверить около 20 серверов и 10 коммутаторов.Мне нужно добавить около 100 переключателей, так что будет только медленнее.Должен быть лучший способ сделать это.Опять же, любая помощь всегда очень ценится.Я, наверное, попробую Munin, но реально мне нужно что-то, что я могу интегрировать в интранет моей компании (PHP).