簡體   English   中英

用於 Windows 服務器和 Cisco 交換機的簡單 PHP 正常運行時間監視器

[英]A simple PHP uptime monitor for Windows Servers and Cisco Switches

我為我們的服務器編寫了(很好地從其他人的代碼拼湊而成)一個非常簡單的正常運行時間監視器 - 它只是一個 ICMP(ping)監視器,它適用於我們有限數量的服務器(20 台左右),而且速度非常快. 這是代碼(我認為實際的 ping 測試功能基於 Birk Jensen 的工作( 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 交換機 - 可能與它執行“ping”的方式有關。

由於大學承諾等原因,我已經很久沒有在這個腳本上做過任何工作了,但我已經盡可能多地做谷歌研究,但我承認我充其量是 2 級或 3 級 PHP n00b。 今天我發現了一些適用於交換機的解決方案,但它們有 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(用於測試,就好像主機離線),在單個 IP 上超時大約需要 5 秒或更長時間,這對我的需要來說太慢了。

是否可以使用多線程的 pcntl_fork 甚至 curl 來做到這一點? 或多個 'exec' 調用或 AJAX 甚至(我願意在這個階段嘗試任何事情)

或某種數據層(第 2 層)Mac 掃描代碼也很棒 - 我不希望任何人編寫完整的代碼,但我敢肯定,以前做過這種事情的人會有一個好主意陷阱以及如何繞過它們。

總而言之 - 一個簡單而容易的解決方案會很好(我會繼續做夢:-D),但任何幫助或建議都非常感謝。

編輯 - 在 PEAR 中嘗試 Net_Ping 的一些建議后,我得到了以下代碼:

<?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,但實際上我需要一些可以集成到我公司的 Intranet (PHP) 中的東西。

您是否嘗試過像Munin這樣的適當監控系統? 眾所周知,它可以工作,而不是您的手工腳本。 我用它來監控我的互聯網連接以及服務器是否可用; 它為此提供了一個 ping 插件。 Munin 也會在出現錯誤時發送郵件並繪制漂亮的圖表。

還有 Nagios 和 Cacti,但我發現 Munin 最容易設置。

如果您真的真的很想繼續單獨使用 PHP,請查看 PEAR 的Net_Ping package,它提供了 API 來發送 ping。

編輯:速度

由於一個接一個地 ping 所有主機太慢,您需要並行化您的 ping。 Net_Ping 不支持此功能,因此您必須並行運行多個 PHP 進程。 使用 PHP 的 pcntl 函數或其中一個shell_exec函數。 ping 腳本只需將主機作為命令行參數進行 ping,並將 ping 的結果記錄在共享日志文件中。 主腳本一直等到所有 ping 腳本結束並收集記錄的信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM