【问题标题】:A simple PHP uptime monitor for Windows Servers and Cisco Switches适用于 Windows 服务器和 Cisco 交换机的简单 PHP 正常运行时间监视器
【发布时间】:2011-05-27 13:07:40
【问题描述】:

我已经为我们的服务器编写了一个非常简单的正常运行时间监视器(从其他人的代码拼凑而成)——它只是一个 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(用于测试,就好像主机离线),大约需要 5 秒或更长时间才能超时单个 IP,这对我的需求来说太慢了。

是否可以使用 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) 中的东西。

【问题讨论】:

    标签: php sockets timeout ping cisco


    【解决方案1】:

    您是否尝试过像Munin 这样的适当监控系统?众所周知,它可以工作,而不是您的手工脚本。我用它来监控我的互联网连接以及服务器是否可用;它为此提供了一个 ping 插件。 Munin 也会在出现错误时发送邮件并绘制漂亮的图表。

    还有 Nagios 和 Cacti,但我发现 Munin 最容易设置。

    如果您真的真的很想继续单独使用 PHP,请查看 PEAR 的 Net_Ping 包,它提供了发送 ping 的 API。

    编辑:速度

    由于一个接一个地 ping 所有主机太慢,您需要并行 ping。 Net_Ping 不支持这一点,因此您必须并行运行多个 PHP 进程。使用 PHP 的 pcntl 函数或 shell_exec 函数之一。 ping 脚本将简单地将主机作为命令行参数进行 ping,并将 ping 的结果记录在共享日志文件中。主脚本一直等到所有 ping 脚本结束并收集记录的信息。

    【讨论】:

    • 谢谢你 - 我会看看 Net_Ping 看看它是否可以在 Windows 上运行。我已经尝试过 Nagios 和一些免费的解决方案,没有一个比商业 IPMonitor 好,我需要更简单的东西,我不愿意尝试另一个 Perl 或 Python 或 Linux 程序并设置它的所有依赖项等只是为了发现它不能满足我的需要,所以我将继续尝试为此手写一个脚本。我什至在尝试一些 ruby​​ 代码,但我没有使用其他人的程序,即使它功能齐全,我也不会从中学到任何东西,而且可能会很麻烦
    • 安装 Munin 只需键入 'apt-get install munin' 并设置一个插件。并且知道如何设置一些监控是值得的。我在家里、我的在线服务器和工作中使用它。 fotostore.cweiske.de/screenshots/…
    • hmmm...好吧..我只是不擅长浏览文档(我承认,如果网站没有为我简化它,我通常不会打扰),但我会看看。我们这里没有 linux 机器,但我总是可以在 virtualbox 中设置 ubuntu 并开始学习。
    • 我在上面做了一个“编辑”,里面有一些新信息(在底部),再次感谢 cweiske
    • 我知道这已经很老了,但我会试一试!
    猜你喜欢
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多