使用PHP对IP地址进行ping操作并输出结果

22

我有以下的函数,目前它不起作用。我想对一个IP地址进行ping操作,然后输出该IP是否存活。

function pingAddress($ip){
    $pingresult = shell_exec("start /b ping $ip -n 1");
    $dead = "Request timed out.";
    $deadoralive = strpos($dead, $pingresult);

    if ($deadoralive == false){
        echo "The IP address, $ip, is dead";
    } else {
        echo "The IP address, $ip, is alive";
    }

}

当我使用以下示例调用此函数时:

pingAddress("127.0.0.1")

无论如何,回显结果始终为“dead”。

请问有人能帮我找出问题所在吗?或者有没有更好的方法可以得到相同的结果?

非常感谢。

更新:已更正代码以包含双引号,但仍然获得相同(不正确)的结果。


2
你需要在调用 shell_exec 时使用双引号,否则 $ip 将不会被替换。 - Clive
嗨,Clive,谢谢 - 我现在使用双引号,但仍然得到相同的结果。 - Bernard
11个回答

18

注意:下面的解决方案无法在Windows上工作。在Linux上,从控制台执行"which ping"命令,并相应地设置建议exec调用的命令路径。

我认为你想要检查命令的退出状态,而shell_exec会给你完整的输出(如果命令输出从版本到版本改变,可能是危险的,出于某种原因)。此外,你的变量$ip没有在单引号中解释。你必须使用双引号""。这可能是使它正常工作所需修复的唯一问题。

但我认为以下代码可以更加“可移植”。在我看来,捕获退出状态实际上比尝试解析结果字符串更好。在我看来,指定ping命令的完整路径也更好。

<?php
function pingAddress($ip) {
    $pingresult = exec("/bin/ping -n 3 $ip", $outcome, $status);
    if (0 == $status) {
        $status = "alive";
    } else {
        $status = "dead";
    }
    echo "The IP address, $ip, is  ".$status;
}

pingAddress("127.0.0.1");

嗨,maraspin,我已经尝试使用上面的函数,但是当我尝试时,即使是999.999.999.999也会显示为活动状态 - 是否还有其他问题?你能提供一些故障排除的建议吗? - Bernard
6
  1. ping,像大多数UNIX命令行实用程序一样,成功时返回0而不是1。
  2. OP正在使用Windows操作系统,因此/bin/ping将无法正常工作。
- user149341
2
删除 /bin/ 目录并将 0 改为 1 看起来已经成功了 - 感谢大家。 - Bernard
1
我建议用一个if语句包裹exec函数的调用,像这样: if(!filter_var($ip, FILTER_VALIDATE_IP) === false){ - dansv130
4
@Michele 尝试使用 -c 开关代替。 - maraspin
显示剩余3条评论

8
这个方法在WordPress中对我也没用。我尝试了-t和-n等其他方式,但都不起作用。我使用的是, ```` add_filter('widget_text', 'do_shortcode'); ````
function pingAddress($ip) {
    $pingresult = exec("/bin/ping -c2 -w2 $ip", $outcome, $status);  
    if ($status==0) {
    $status = "alive";
    } else {
    $status = "dead";
    }
    $message .= '<div id="dialog-block-left">';
    $message .= '<div id="ip-status">The IP address, '.$ip.', is  '.$status.'</div><div style="clear:both"></div>';    
    return $message;
}
// Some IP Address
pingAddress("192.168.1.1"); 

这对我来说非常完美,终于解决了。 我从http://www.phpscriptsdaily.com/php/php-ping/ 参考了这个内容。 希望这会有所帮助。

好的,我想对此进行修改,因为它在我的本地主机上运行良好,但是在我的生产服务器上不行。 对于生产服务器,我得到了另一种方法,现在可以在本地和生产环境下都能正常工作。

$fp = fSockOpen($ip,80,$errno,$errstr,1);
if($fp) { $status=0; fclose($fp); } else { $status=1; }

然后我展示服务器的状态,0代表服务器正常,1代表服务器宕机。

对我来说这个方法非常完美。我是从Ping site and return result in PHP中获得的。感谢@karim79。


6
我已经开发了一个算法,可以使用异构操作系统,包括Windows和Linux。
实现以下类:
<?php

    class CheckDevice {

        public function myOS(){
            if (strtoupper(substr(PHP_OS, 0, 3)) === (chr(87).chr(73).chr(78)))
                return true;

            return false;
        }

        public function ping($ip_addr){
            if ($this->myOS()){
                if (!exec("ping -n 1 -w 1 ".$ip_addr." 2>NUL > NUL && (echo 0) || (echo 1)"))
                    return true;
            } else {
                if (!exec("ping -q -c1 ".$ip_addr." >/dev/null 2>&1 ; echo $?"))
                    return true;
            }

            return false;
        }
    }

    $ip_addr = "151.101.193.69"; #DNS: www.stackoverflow.com

    if ((new CheckDevice())->ping($ip_addr))
        echo "The device exists";
    else 
        echo "The device is not connected";

3
请勿在多个问题中发布类似的答案。而是要根据所问的问题量身定制答案。如果问题过于广泛或彼此重复,请标记给管理员处理。 - Samuel Liew

3
我刚刚结合上述所有知识编写了一个非常快速的解决方案。
    function pinger($address){
        if(strtolower(PHP_OS)=='winnt'){
            $command = "ping -n 1 $address";
            exec($command, $output, $status);
        }else{
            $command = "ping -c 1 $address";
            exec($command, $output, $status);
        }
        if($status === 0){
            return true;
        }else{
            return false;
        }
    }

2
我喜欢这个!对于我所需要的问题,这是一个很好的答案。 - Teku1998

2

对于Windows,请使用此类

$host = 'www.example.com';
$ping = new Ping($host);
$latency = $ping->ping();
if ($latency !== false) {
 print 'Latency is ' . $latency . ' ms';
}
else {
print 'Host could not be reached.';
}

https://github.com/geerlingguy/Ping


2

这对我来说很好用。

$host="127.0.0.1";
$output=shell_exec('ping -n 1 '.$host);

echo "<pre>$output</pre>"; //for viewing the ping result, if not need it just remove it

if (strpos($output, 'out') !== false) {
    echo "Dead";
}
    elseif(strpos($output, 'expired') !== false)
{
    echo "Network Error";
}
    elseif(strpos($output, 'data') !== false)
{
    echo "Alive";
}
else
{
    echo "Unknown Error";
}

1

基于@tiamiyu-saheed-oluwatosin的好答案,我用简洁的if/else(三元)风格编写了这个小函数,在Windows和Linux上都可以工作,用于检查我的局域网中是否有第二个PHP服务器正在运行。

function running($ip) {
    exec("ping -{strtolower(PHP_OS)=='winnt'?'n':'c'} 1 $ip", $out, $res);
    return ($res === 0 ? true : false);
}

使用:
if(running('192.168.1.20') {
    // execute some code...
}

0

在尝试以下示例之前,请检查您的 ping 命令的手册页面(始终是一个好习惯)。例如,对于 Ubuntu16,接受的答案不起作用,因为 -n 3 失败了(这不再是包的计数,-n 表示不将 IP 地址转换为主机名)。

根据 OP 的请求,一个潜在的替代函数如下:

function checkPing($ip){
    $ping = trim(`which ping`);
    $ll = exec($ping . '-n -c2 ' . $ip, $output, $retVar);
    if($retVar == 0){
        echo "The IP address, $ip, is alive";
        return true;
    } else {
        echo "The IP address, $ip, is dead";
        return false;
    }
}

0
这是与我一起工作的内容:
<?php
class CheckDevice {
    public function myOS(){
        if (strtoupper(substr(PHP_OS, 0, 3)) === (chr(87).chr(73).chr(78)))
            return true;
        return false;
    }
    public function ping($ip_addr){
        if ($this->myOS()){
            if (!exec("ping -n 1 -w 1 ".$ip_addr." 2>NUL > NUL && (echo 0) || (echo 1)"))return true;
        } else {
            if (!exec("ping -q -c1 ".$ip_addr." >/dev/null 2>&1 ; echo $?"))
                return true;
        }return false;
    }
}
$ip_addr = "192.168.1.1";
if ((new CheckDevice())->ping($ip_addr))
    echo "The device exists";
else 
    echo "The device is not connected";

0

这对主机名、反向IP(用于内部网络)和IP都可以正常工作。

function pingAddress($ip) {
    $ping = exec("ping -n 2 $ip", $output, $status);
    if (strpos($output[2], 'unreachable') !== FALSE) {
        return '<span style="color:#f00;">OFFLINE</span>';
    } else {
        return '<span style="color:green;">ONLINE</span>';
    }
}

echo pingAddress($ip);

永远不要直接在 exec 中使用用户输入。请参考这个问题以了解正确的方法来清理用户输入数据。 - Linek
是的,没错。在我的代码中,我有一个围绕着 $_get 的 sanitize 函数,但这与本问题无关,所以我将其删除了。编辑:为了更清晰,我删除了 $_get 参数。 - ChristianG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接