PHP Ping Script erweitern

Xxplozive

..::=Area51=::.., ,
Moin,

ich habe mir ein kleines Script geschrieben welches mir beim Aufrufen des Scriptes (Cronjob) eine Push Nachricht auf mein Android-Smartphone schicken soll, wenn ein Server nicht anpingbar ist. Das klappt soweit auch richtig gut. Sobald ein Server bzw Port nicht erreichbar ist, bekomme ich die Benachrichtigung auf mein SGS3. Doch jetzt möchte ich es so haben, das wenn mir das Script mir mitteilt das der Server offline ist, ich nicht alle 5 Minuten (im Cronjob eingestellte Zeit) die Meldung bekomme das der Server Down ist.

Wie kann ich die letzte Aktion jetzt unterdrücken? Es kann auch gerne eine Push-Nachricht versendet werden, wenn der Server wieder erreichbar ist.

ping.php
Code:
<?php
require dirname(__FILE__).'/nmaApi.class.php';

// API Key von "Notify my Android"
$apikey = "APIKEY";

$nma = new nmaApi(array('apikey' => $apikey));

$servername = array("127.0.0.1", "192.168.0.1", "192.168.0.2", "192.168.0.3", "192.168.0.4", "192.168.0.5");

$ip = array("Localhost", "IP1", "IP2", "IP3", "IP4", "IP5");

$port = array("80", "21", "8010", "112", "135", "21");

$zeahler = 0;

$timeout = 2;

while ($zeahler < 6){

$fp = @fsockopen($ip[$zeahler], $port[$zeahler], $errno, $errstr, $timeout);

    if($fp)

        {
        echo $ip[$zeahler]. $port[$zeahler]. $servername[$zeahler]."<font color=\"green\"><b> = Online </b></font><br>";
        fclose($fp);
        $zeahler++;
        }

    else

        {
        echo $ip[$zeahler]. $port[$zeahler]. $servername[$zeahler]."<font color=\"red\"><b> = Offline </b></font>";
		if($nma->verify()){
			if($nma->notify($ip[$zeahler], $servername[$zeahler], 'PINGTEST! Port '.$port[$zeahler].' ist nicht erreichbar.')){
			echo "Notifcation sent!<br>";
			}
		}
        $zeahler++;
		}

}

?>


nmaApi.class.php
Code:
<?php

class nmaApi
{

    /**
     * @const LIB_ERROR_TYPE can be exception or error
     */
    const LIB_ERROR_TYPE = 'error';

    /**
     * @const holds the api key verify url
     */
    const LIB_NMA_VERIFY = 'https://www.notifymyandroid.com/publicapi/verify';

    /**
     * @const holds the notify url
     */
    const LIB_NMA_NOTIFY = 'https://www.notifymyandroid.com/publicapi/notify';

    /**
     * toggles on debugging
     *
     * @var bool
     */
    public $debug = false;

    public $apiCallsRemaining = false;

    public $apiLimitReset = false;

    public $lastStatus = false;
    /**
     * @var bool|string
     */
    protected $apiKey = false;

    /**
     * @var bool|string
     */
    protected $devKey = false;


    protected $error_codes
        = array(
            200     => 'Notification submitted.',
            400     => 'The data supplied is in the wrong format, invalid length or null.',
            401     => 'None of the API keys provided were valid.',
            402     => 'Maximum number of API calls per hour exceeded.',
            500     => 'Internal server error. Please contact our support if the problem persists.'
        );

    /**
     * @param array $options
     */
    function __construct($options = array())
    {
        if (!isset($options['apikey'])) {
            return $this->error('You must supply a API Key');
        } else {
            $this->apiKey = $options['apikey'];
        }

        if (isset($options['developerkey'])) {
            $this->devKey = $options['developerkey'];
        }

        if (isset($options['debug'])) {
            $this->debug = true;
        }

        return true; // this shuts my ide up

    }


    /**
     * @param bool $key [optional] if not set the one used on construct is used
     *
     * @return bool|mixed|SimpleXMLElement|string
     */
    public function verify($key = false)
    {

        $options = array();

        if ($key !== false) {
            $options['apikey'] = $key;
        } else {
            $options['apikey'] = $this->apiKey;
        }


        if ($this->devKey) {
            $options['developerkey'] = $this->devKey;
        }

        return $this->makeApiCall(self::LIB_NMA_VERIFY, $options);
    }

    /**
     * @param string $application
     * @param string $event
     * @param string $description
     * @param int    $priority
     * @param bool   $apiKeys
     *
     * @return bool|mixed|SimpleXMLElement|string
     */
    public function notify($application = '', $event = '', $description = '', $priority = 1, $apiKeys = false)
    {
        if (empty($application) || empty($event) || empty($description)) {
            return $this->error('you must supply a application name, event and long desc');
        }

        $post = array('application' => substr($application, 0, 256),
                      'event'       => substr($event, 0, 1000),
                      'description' => substr($description, 0, 10000),
                      'priority'    => $priority
        );

        if ($this->devKey) {
            $post['developerkey'] = $this->devKey;
        }

        if ($apiKeys !== false) {
            $post['apikey'] = $apiKeys;
        } else {
            $post['apikey'] = $this->apiKey;
        }

        return $this->makeApiCall(self::LIB_NMA_NOTIFY, $post, 'POST');
    }


    /**
     * @param        $url
     * @param null   $params
     * @param string $verb
     * @param string $format
     *
     * @return bool|mixed|SimpleXMLElement|string
     * @throws Exception
     */
    protected function makeApiCall($url, $params = null, $verb = 'GET', $format = 'xml')
    {
        $cparams = array(
            'http' => array(
                'method'        => $verb,
                'ignore_errors' => true
            )
        );
        if ($params !== null && !empty($params)) {
            $params = http_build_query($params);
            if ($verb == 'POST') {
                $cparams["http"]['header'] = 'Content-Type: application/x-www-form-urlencoded';
                $cparams['http']['content'] = $params;
            } else {
                $url .= '?' . $params;
            }
        } else {
            return $this->error(
                'this api requires all calls to have params' . $this->debug ? ', you provided: ' . var_dump($params)
                    : ''
            );
        }

        $context = stream_context_create($cparams);
        $fp = fopen($url, 'rb', false, $context);
        if (!$fp) {
            $res = false;
        } else {

            if ($this->debug) {
                $meta = stream_get_meta_data($fp);
                $this->error('var dump of http headers' . var_dump($meta['wrapper_data']));
            }

            $res = stream_get_contents($fp);
        }

        if ($res === false) {
            return $this->error("$verb $url failed: $php_errormsg");
        }

        switch ($format) {
            case 'json':
                return $this->error('this api does not support json');
            /*
            * uncomment the below if json is added later
            * $r = json_decode($res);
           if ($r === null) {
               return $this->error("failed to decode $res as json");
           }
           return $r;*/

            case 'xml':
                $r = simplexml_load_string($res);
                if ($r === null) {
                    return $this->error("failed to decode $res as xml");
                }
                return $this->process_xml_return($r);
        }
        return $res;
    }

    /**
     * @param     $message
     * @param int $type
     *
     * @return bool
     * @throws Exception
     */
    private function error($message, $type = E_USER_NOTICE)
    {
        if (self::LIB_ERROR_TYPE == 'error') {
            trigger_error($message, $type);
            return false;
        } else {
            throw new Exception($message, $type);
        }
    }

    /**
     * @param SimpleXMLElement $obj
     *
     * @return bool
     */
    private function process_xml_return(SimpleXMLElement $obj)
    {

        if (isset($obj->success)) {
            $this->lastStatus = $obj->success["@attributes"]['code'];

            $this->apiCallsRemaining = $obj->success["@attributes"]['remaining'];
            $this->apiLimitReset = $obj->success["@attributes"]['resettimer'];
            return true;
        } elseif (isset($obj->error)) {
            if (isset($obj->error["@attributes"])) {
                $this->lastStatus = $obj->error["@attributes"]['code'];

                if (isset($obj->error["@attributes"]['resettimer'])) {
                    $this->apiLimitReset = $obj->error["@attributes"]['resettimer'];
                }

            }
            return $this->error($obj->error);
        } else {
            return $this->error("unkown error");
        }
    }

}
 
Hi,

du könntest dir z.B. noch ein Array $online anlegen. Darin speicherst du dann erstmal 6-mal den Wert true. Dann kannst du dein if($fp)...else erweitern.
Im if-Zweig, also wenn der Server erreichbar ist, machst du dann noch eine Abfrage ob $online[$zaehler] == false ist. Wenn das der Fall ist, heißt das, dass der Server beim letzten Versuch nicht erreichbar war. Also kannst du dir per $nma->notify eine Nachricht schicken lassen, dass der Server wieder online ist. Dann $online[$zaehler] wieder auf true setzen.
Im else-Zweig, also der Server ist nicht erreichbar, schaust du, ob $online[$zaehler] == true ist. Das bedeutet dann, dass der Server bei der letzten Prüfung erreichbar war und jetzt nicht mehr. Also schickst du dir nur dann eine Nachricht, wenn der letzte Status eben true war, und setzt dann $online[$zaehler] auf false.

PS: Mir fällt gerade auf das du meintest, dass du das Skript per Cronjob startest. Heißt also, das Skript wird immer wieder beendet und neu gestartet. Somit verlierst du dann natürlich auch immer wieder dein $online-Array. Heißt das musst du dir dann irgendwie zwischenspeichern. Also eventuell wenn du eh schon eine Datenbank verwendest da drin, oder, was einfacher und in diesem Szenario sicher auch ausreichend ist, einfach den Status in eine einfache Textdatei speichern und die dann immer einlesen und speichern.
 
Hmmm,

dann muß ich mal versuchen das ganze für mySQL umzubauen. Nur leider hab ich noch null Erfahrung mit PHP und SQL. Bin schon froh das ich das ping.php Script selbst zusammengebastelt bekommen habe. :) Aber wenn ich es erweitert habe, werde ich mich nochmal melden :)

Greetz Xx
 
Wenn Du noch keine Erfahrung mit SQL hast, würde ich Dir empfehlen, die Daten in einer Textdatei abzuspeichern. Die Daten kann man bequem wieder (in ein Array, soweit ich mich erinnere) einlesen und nutzen. Nur hierfür extra SQL zu lernen halte ich für überflüssig.
 
Oben