PHP: Ping with Pear

Status
Not open for further replies.

Baljeet

Member
Jan 31, 2011
76
0
I had to write a ping utility at work and based on the ping results from three different locations I had to present the user with a different website (front-page). Being a fan of PEAR packages I found . Within minutes I had a working ping program but I thought I would present the information to you.

This tutorial assumes you have a working installation of Pear and it is updated. At the time of this witting I will be using Net_Ping 2.4.3. You can find the documentation for Net_Ping here:

Installing Net_Ping
As always, installation of PEAR packages is extremely simple. Drop to your command prompt, open up a terminal, or SSH into your box and issue the command:

Code:
# pear install net_ping
If all goes well you should see results similar to this:

Code:
downloading Net_Ping-2.4.3.tgz ...
Starting to download Net_Ping-2.4.3.tgz (9,634 bytes)
.....done: 9,634 bytes
install ok: channel://pear.php.net/Net_Ping-2.4.3
You now have PEAR::Net_Ping installed.

Alternatively:
If your host is running cPanel you can install PEAR modules using the cPanel GUI.


Using the Module
Using the PEAR Package is as easy as including it.

PHP:
require ("Net/Ping.php");
Now you will need to create the Object:

PHP:
$pingObj = Net_Ping::factory();
And ping the IP or Hostname of your choice:

PHP:
$response = $pingObj->ping('codecall.net');
print_r($response);
The complete script looks like this:

PHP:
<?php
require ("Net/Ping.php");

$pingObj = Net_Ping::factory();
$response = $pingObj->ping('codecall.net');
print_r($response);

?>
Now this example is the most basic of examples and doesn't even check if the PEAR Object was created. Using the isError function of the PEAR class we can determine if the object thrown back is actually an error message.

isError() examines whether a variable is a PEAR_Error object and - optional - contains a specific error message or code. Read More:

Adding that to our code it becomes:

PHP:
<?php
require ("Net/Ping.php");

$pingObj = Net_Ping::factory();

if(PEAR::isError($ping)) {
         echo $ping->getMessage();
 } else {
         $response = $pingObj->ping('codecall.net');
         print_r($response);
}
?>
If you execute the code above you will get some nasty results:

You can fix this by adding <pre> </pre> tags around the array dump:

PHP:
<?php
require ("Net/Ping.php");

$pingObj = Net_Ping::factory();

if(PEAR::isError($ping)) {
         echo $ping->getMessage();
 } else {
         $response = $pingObj->ping('codecall.net');

     echo "<pre>";
         print_r($response);
     echo "</pre>";
}
?>
Which will now produce a more aesthetic result:

Code:
Net_Ping_Result Object
(
    [_icmp_sequence] => Array
        (
            [0] => 95
            [1] => 152
            [2] => 118
        )

    [_target_ip] => 67.205.118.30
    [_bytes_per_request] => 32
    [_bytes_total] => 96
    [_ttl] => 50
    [_raw_data] => Array
        (
            [0] => 
            [1] => Pinging codecall.net [67.205.118.30] with 32 bytes of data:
            [2] => Reply from 67.205.118.30: bytes=32 time=95ms TTL=50
            [3] => Reply from 67.205.118.30: bytes=32 time=152ms TTL=50
            [4] => Reply from 67.205.118.30: bytes=32 time=118ms TTL=50
            [5] => 
            [6] => Ping statistics for 67.205.118.30:
            [7] =>     Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
            [8] => Approximate round trip times in milli-seconds:
            [9] =>     Minimum = 95ms, Maximum = 152ms, Average = 121ms
        )

    [_sysname] => windows
    [_round_trip] => Array
        (
            [min] => 95
            [max] => 152
            [avg] => 121
        )

    [_transmitted] => 3
    [_received] => 3
    [_loss] => 0
)
Arguments
The code above isn't very useful, has no comments, and doesn't do anything. For my purpose I needed to check the the Packet _loss amount and I needed to limit the ping attempts to 1.

I looked through the documentation and searched on the web a bit but could not find an argument list anywhere. At face value it looks like the above code is as much as you can control the Ping object so I dug through the Net/Ping.php file and discovered a setArgs() function and a _createArgList() function. In the _createArgList() function is a list of paramters you can pass to setArgs:

Code:
timeout
iface
ttl
count
quiet
size
seq
deadline
As you can see from above, most ping options are available as pass through arguments.

Setting the Arguments
To set the arguments you need to pass an associative array to the setArgs() method. Here is how:

PHP:
$pingObj->setArgs(array('count' => 1, 'ttl' => 50, 'timeout' => 100));

Here is our complete script:

PHP:
<?php

/**
 * Include the PEAR Ping Class
 * 
 * @uses Pear::Net_Ping
 *  
 */
require ("Net/Ping.php");

/**
 * Create the Ping Object/Class
 */
$pingObj = Net_Ping::factory();

/**
 * If there is no error in creating the
 * ping class then ping our source
 */
if(PEAR::isError($ping)) {
         echo $ping->getMessage();
 } else {
    // Set the arguments
    $pingObj->setArgs(array('count' => 1, 'ttl' => 50, 'timeout' => 100));

    // Ping the Host
    $response = $pingObj->ping('codecall.net');
        
    print "<pre>";
    print_r($response);
    print "</pre>";
}


?>
For my needs at work I've added several more functions that aren't relevant here. Below I will show you a better need for the system.

A Practical Need
Justin from needed a ping script which emailed him on failure. It will run on the CodeCall server every 5 minutes (via cron job) and send him an alert if his server is down. Here are his requirements:


  1. 10 Pings @ 5 Minute Intervals (controlled via cron)
  2. Email @ 90% failure alert (9/10 pings fail)
  3. Server IP: 74.55.90.58 (AmpHosted.com)
  4. Information Requested - Times Failed, Ping Responses
Taking the job information above we can create a simple ping script:

PHP:
<?php

// {{{ Header
/**
 * AmpHosted.com Ping Test Script
 * 
 * Pings AmpHosted.com 9 times and determines fail rate.  
 * 
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2008 CodeCall.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted under the terms of the BSD License.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * @category  Reports      
 * @author    Jordan (CodeCall.net)
 * @date     10-2-2008
 * @version   1.0
 * @link      http://www.codecall.net
 * @copyright 2008 CodeCall.net
 * @uses       PEAR::Net_Ping and Beyond
 */

// }}}
// {{{ Includes
/**
 * Include the PEAR Ping Class
 *  
 */
require ("Net/Ping.php");

// }}}
// {{{ PHP Time Limit

/**
 * If the server is unresponsive
 * the script may take longer to 
 * respond than the default 30 seconds
 * 
 */
set_time_limit(200);

// }}}
// {{{ Defines

/**
 * Define our paramters
 */
define('FAILURE_RATE', 9);
define('PING_RATE', 10);
define('HOST_NAME', '74.55.90.58');
define('TIMEOUT', 200);

// }}}
// {{{ Variables

/**
 * Common Email Variables
 */
$emailBody         = FAILURE_RATE 
                 . " or more pings failed!" 
                 . PHP_EOL 
                 . "Ping Results: "
                  ;                                         
$emailSubject     = "Ping Respinse Failed - AmpHosted01";
$emailAddress     = "[email protected]";        

// }}}
// {{{ Content

/**
 * Create the Ping Object/Class
 */
$pingObj = Net_Ping::factory();

/**
 * If there is no error in creating the
 * ping class then ping our source
 */
if(PEAR::isError($ping)) {
         echo $ping->getMessage();
 } else {
    // Set the arguments
    $pingObj->setArgs(array('count' => PING_RATE, 'timeout' => TIMEOUT));

    // Ping the Host
    $response = $pingObj->ping(HOST_NAME);
        
    // Determine the fail rate
    if ($response->getLoss() >= FAILURE_RATE) {
        foreach($response->getRawData() as $data) {
            $emailBody .= $data . PHP_EOL;    
        }
        
        // Send email
        mail($emailAddress, $emailSubject, $emailBody);
        
        // Print Error
        echo "Error, sending Email!" . PHP_EOL;
    } 
        
}

// }}}

?>
Note
If you are under a cPanel host and you install your PEAR scripts via cPanel or via SSH you will need to use the full include path. You can find your full PEAR include path by going to "cPanel/PHP PEAR Packages". For CodeCall the PEAR location is "/home/codecall/php" so my Net_Ping Require would look like this:

PHP:
require ("/home/codecall/php/Net/Ping.php");
EOF
That is it! If you have any questions ask me. If you want to know how it works ask phpForFun (Justin from AmpHosted.com).

All Credits goes to one who really made this...
 
Status
Not open for further replies.

Users who are viewing this thread

Top