22

I have the following function that I doesn't work so far. I would like to ping an IP address and then to echo whether the IP is alive or not.

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";
    }

}

When I call this function using the example:

pingAddress("127.0.0.1")

The echo result is always 'dead' - no matter what.

Could someone please help me where I'm going wrong? And/OR is there a better method of doing this with the same result?

Many thanks.

Update: Have amended code to include the double quotes but still getting the same (incorrect) results.

STT LCU
  • 4,348
  • 4
  • 29
  • 47
Bernard
  • 1,209
  • 3
  • 17
  • 22

11 Answers11

18

NOTE: Solution below does not work on Windows. On linux exec a "which ping" command from the console, and set command path (of the suggested exec call) accordingly

I think you want to check the exit status of the command, whereas shell_exec gives you full output (might be dangerous shall command output change from command version to version. for some reason). Moreover your variable $ip is not interpreted within single quotes. You'd have to use double ones "". That might be the only thing you need to fix in order to make it work.

But I think following code can be more "portable". IMHO it is in fact better to catch the exit status, rather than trying to parse result string. IMHO it's also better to specify full path to ping command.

<?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
  • 2,353
  • 20
  • 16
  • HI maraspin, have tried using this function above exactly but this will say even 999.999.999.999 is alive when I try it - could there be anything else wrong? Could you suggest any troubleshooting tips? – Bernard Nov 06 '11 at 23:22
  • 6
    **1)** `ping`, like most UNIX command-line utilities, returns 0 on success, not 1. **2)** The OP is using Windows, so `/bin/ping` won't work. –  Nov 06 '11 at 23:27
  • 2
    removing /bin/ and changing 0 to 1 looks to have worked - thanks all. – Bernard Nov 06 '11 at 23:39
  • @duskwuff: you're right, my bad. I didn't even consider 1 (and had all other UNIX std error codes in mind), but on first edit I had put worst case first; I then decided it was better practice to have nominal case first. But forgot to replace != with ==. That's where problem was. Fixed in the code above. As for the /bin/ping path, you're also right. +1d. In my answer command needs to be changed to whatever ping command location you need to invoke. – maraspin Nov 06 '11 at 23:42
  • @Bernard I suggest you to use a comparison w/ 0 (for successful case), rather than relying on a match with 1 on failure. Other codes different from 1 can also be a sign of bad outcome for execution... – maraspin Nov 06 '11 at 23:54
  • 1
    I suggest wrapping the exec with an if statement like `if(!filter_var($ip, FILTER_VALIDATE_IP) === false){` – dansv130 Apr 05 '16 at 09:10
  • in linux, I get connect: Invalid argument with -n and 3 as arguments to ping – Michele Dec 20 '17 at 14:32
  • 4
    @Michele try using the -c switch instead – maraspin Jan 16 '18 at 15:37
8

This also did not work for me in Wordpress. I also tried -t and -n and other ways, but did not work. I used,

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"); 

This worked perfectly for me, finally. I referred this from http://www.phpscriptsdaily.com/php/php-ping/ Hope this will help

Well I want to modify this as it is working fine on my localhost but not on my live server For live server, I got another thing which now works for both local as well as live.

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

Then I show the Server is up for 0 and down for 1.

This works perfectly for me. I got this from Ping site and return result in PHP Thanks @karim79

Community
  • 1
  • 1
6

I have developed the algorithm to work with heterogeneous OS, both Windows and Linux.

Implement the following class:

<?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";
Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
Antonio Moreno
  • 881
  • 8
  • 9
  • 3
    Please do not re-post similar answers to multiple questions. Instead, tailor the answer to the question asked. If the question is too broad or are duplicates of each other, please flag for a moderator instead. – Samuel Liew Mar 28 '18 at 23:57
3

i just wrote a very fast solution by combining all knowledge gain above

    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

this works fine for me..

$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";
}
2

For Windows Use this class

$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

Kuldeep
  • 29
  • 1
1

Based on the great answer of @tiamiyu-saheed-oluwatosin I wrote this small function in shorthand if/else (ternary) style, working on both Windows and Linux, to check if a second PHP server is up and running in my LAN.

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

Use :

if(running('192.168.1.20') {
    // execute some code...
}
Meloman
  • 3,558
  • 3
  • 41
  • 51
0

This works fine with hostname, reverse IP (for internal networks) and 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);
ChristianG
  • 458
  • 4
  • 11
  • Never ever use user input directly in `exec`. See [this question](http://stackoverflow.com/q/982904/2008285) for a correct way to sanitize user input data. – Linek Mar 22 '17 at 12:16
  • Yhe, true. In my code I have a sanitize function around $_get, but kinda not relevant for this question, so I removed it.Edit: Removed the $_get parameter to be clear. – ChristianG Mar 22 '17 at 12:21
0

Do check the man pages of your ping command before trying some of these examples out (always good practice anyway). For Ubuntu 16 (for example) the accepted answer doesn't work as the -n 3 fails (this isn't the count of packets anymore, -n denotes not converting the IP address to a hostname).

Following the request of the OP, a potential alternative function would be as follows:

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;
    }
}
bnoeafk
  • 489
  • 4
  • 16
0

This is work with me:

<?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";
James Risner
  • 5,451
  • 11
  • 25
  • 47
-1

I use this function :

<?php
function is_ping_address($ip) {
    exec('ping -c1 -w1 '.$ip, $outcome, $status);
    preg_match('/([0-9]+)% packet loss/', $outcome[3], $arr);
    return ( $arr[1] == 100 ) ? false : true;
}
Mcile
  • 128
  • 6