Ethernut Home Hardware Firmware Tools Download Community
 
 
Suche | Legals | English

Serverüberwachung

Überblick

Diese Beispielanwendung ServerWatch überwacht ein oder mehrere externe Server. Bei einem Ausfall oder Re-aktivierung eines Servers wird eine SMS versendet. Zusätzlich besteht die Möglichkeit, bei Statusänderungen einen SNMP Trap zu schicken und den aktuellen Status auf einem Cloudserver von ThingSpeak oder Xively zu archivieren.

Hardware

Die Software wurde für ein Ethernut 2 Board erstellt und mit diesem getestet. Obwohl kein besonderer Wert auf Portabilität gelegt wurde, sollte eine Anpassung an andere Boards kein großes Problem darstellen.

Zum Verschicken von SMS-Nachrichten benötigt man zusätzlich ein GSM-Modem. Die Software ist für das Locmote Add-On vorbereitet, welches ein SIM908 GSM-Modul des Herstellers Simcom enthält. Ethernut 2 bietet zwei USARTs. Davon wird USART0 zur Ausgabe von Statusmeldungen verwendet und USART1 ist über den Expansion Port mit dem GSM-Modem verbunden.

Auf Locmote befindet sich eine kleine ATtiny-CPU, die einige grundlegende Funktionen wie das Ein- und Ausschalten des Moduls steuert und vom Ethernut Board über die I2C-Schnittstelle angesprochen wird.

Alternativ kann man natürlich ein externes GSM-Modem verwenden, wenn die Software entsprechend angepasst wird. In den meisten Fällen wird dies darauf beschränkt bleiben, die speziellen Routinen für den I2C-Bus zu entfernen. Mit Hilfe eines sog. Splitter-Kabels kann man sowohl das externe Modem als auch die serielle Verbindung zum PC mit dem DB-9 Stecker des Ethernut Boards zu verbinden. Dabei werden die Handshake-Leitungen RTS und CTS als Empfangs- und Sendeleitung für das Modem "missbraucht".

Näheres zur RS-232 Verkabelung und den entsprechenden Jumper-Einstellungen findet man übrigens auf der Seite Ethernut RS-232 Primer.

Quellcode

Der komplette Quellcode befindet sich in der Datei
serverwatch.zip
Kopieren Sie den Inhalt des Archivs in ein nutapp-Verzeichnis, welches Sie mit dem Konfigurator für Ethernut 2.1 erstellt haben. Verwendet wurde hier Nut/OS 5.2, die Binärfiles wurden unter Windows 7 mit der Toolchain MHV AVR Tools (GCC 4.7.2) von Make Hack Void erstellt.

Da die Konfiguration direkt im Quellcode vorgenommen wird, gibt es keine fertige Binärdatei für Ethernut 2. Diese muss in jeden Fall selbst erstellt werden. Wenn Sie noch keine Anwendungen für Ethernut 2 erstellt haben, finden Sie im NutWiki eine Einführung dazu.

Konfiguration

Die gesamte Konfiguration ist in der aktuellen Version hart kodiert. Dies reicht für eine einfache Anwendung aus, da Serverstrukturen relativ selten geändert werden. Für einen universelleren Einsatz wäre ein Webinterface zur Konfiguration und Statusanzeige denkbar. Dafür steht die leistungsfähige microHTTP Bibliothek zur Verfügung.

Alle grundsätzlichen Einstellung befinden sich in der Datei serverwatch.h. Die wichtigste Einstellung ist die Telefonnummer, an die die SMS-Nachrichten gehen sollen.

#define SMS_TARGET "555"

Falls Sie Statusänderungen per SNMP-Trap gemeldet haben wollen, ist mit

#define TRAP_TARGET "192.168.1.2"

deren Zieladresse festzulegen. Anmerkung: Zur Zeit kann man hier noch keinen Hostnamen, sondern nur feste IP-Adressen eintragen.

Der aktuelle Status kann regelmäßig an einen Cloudserver gesendet werden. Bisher werden ThingSpeak und Xively (ehemals Cosm, Pachube) unterstützt. Für ThingSpeak reicht der Eintrag des API-Keys.

#define THINGSPEAK_API_KEY  "MAFJSA5LDKFJJ7"

Die Aktivierung für den Xively Cloud benötigt zwei Angaben, die Feed-ID und den API-Key.

#define XIVELY_FEED_ID  55555
#define XIVELY_API_KEY  "mafjsa5ldkfjj7^sdfkljfsadf"

Weiter unten in der Datei serverwatch.h finden Sie die globale Struktur _NODE_INFO, in der die Konfiguration und der aktuelle Status jedes zu überwachenden Servers gespeichert wird. Die Kommentare im Quellcode enthalten dazu einige nützliche Hinweise. Das Setzen der Konfigurationsparameter selbst geschieht in der lokalen Funktion ConfigNodes, die sich in der Datei serverwatch.c befindet.

static void ConfigNodes(void)
{
    int i;

    for (i = 0; i < MAX_NODES; i++) {
        nodes[i].n_icmp_timeout = 2000;
        nodes[i].n_icmp_retries = 3;
        nodes[i].n_up_interval = 60000;
        nodes[i].n_dn_interval = 10000;
    }

    nodes[0].n_name = "Internet router";
    nodes[0].n_ip = inet_addr("192.168.1.1");

    nodes[1].n_name = "Virtual server";
    nodes[1].n_ip = inet_addr("55.55.55.55");
    nodes[1].n_depnode = &nodes[0];

    nodes[2].n_name = "www.example.com";
    nodes[2].n_depnode = &nodes[1];
    nodes[2].n_ports[0] = 80;

    nodes[3].n_name = "mail.example.com";
    nodes[3].n_depnode = &nodes[1];
    nodes[3].n_ports[0] = 25;
    nodes[3].n_ports[1] = 110;
    nodes[3].n_ports[2] = 143;
}

Das vorgegebene Beipiel ist so nicht lauffähig und dient lediglich der Anschauung. Die Schleife am Anfang setzt einige Standardwerte, die für jeden eingetragenen Server gelten sollen.

Wie oben zu sehen ist, muss jeder Eintrag für einen zu überwachenden Server einen Namen haben. Dieser wird in den Meldungstexten verwendet. Die Angabe der IP-Adresse ist optional. Fehlt deren Angabe, dann muss der Name gleich dem DNS-Hostnamen des Rechners sein. Die IP-Adresse wird in diesem Fall mit einer DNS-Anfrage aufgelöst.

Optional können für jeden Server bis zu 7 TCP-Ports konfiguriert werden.

Falls gesetzt, verweist die Membervariable n_depnode auf einen Servereintrag, von dem der aktuelle Servereintrag abhängig ist. Im Beispiel oben sind der Webserver www.example.com und der Mailserver mail.example.com als virtuelle Maschinen auf dem Server mit der IP-Adresse 55.55.55.55 implementiert und daher von diesem abhängig. Diese Host ist wiederum davon abhängig, dass der Internetrouter ereichbar ist. Dies führt dazu dass, beim Ausfall des Internetrouters alle übrigen Server nicht weiter überwacht werden und auch keine Störungsmeldungen verursachen.

Wenn Sie serverwatch.c und serverwatch.h auf Ihre Umgebung angepasst haben, können Sie das Programm wie gewohnt übersetzen und die Binärdatei auf das Ethernut Board übertragen.

Programmablauf

Um den Ablauf verfolgen zu können, ist wie üblich ein Terminalprogramm auf dem PC zu starten und die RS-232 Schnittstelle des Ethernut Boards mit dem PC zu verbinden, ggf. über eine USB/RS-232 Bridge, falls der PC über keine interne serielle Schnittstelle verfügt. Die Einstellung ist 115200,N,8,1.

Im ersten Schritt wird eine kurze Versionsmeldung ausgegeben und der I2C-Bus initialisiert. Wie bereits erwähnt, kommuniziert Ethernut mit dem ATtiny auf dem Locmot Board über diese Schnittstelle.

ServerWatch - Nut/OS 5.2.0.0 - Jun 19 2013 19:33:28
Init I2C...speed...20035 bps
Locmote power on ... OK

Danach wird die Ethernet-Schnittstelle aktiviert und die lokale IP-Adresse per DHCP angefragt.

Register Ethernet eth0...OK
Configure Ethernet...192.168.1.203 ready

War dies erfolgreich, wird nun das GSM-Modem initialisiert.

Initialize Modem UART...OK
TMO: 0 -> 1000
FLU:
TMO: 1000 -> 0
TMO: 0 -> 2000
CMD(002): AT
RSP(002): OK
TMO: 2000 -> 200
CMD(003): ATZ
RSP(002): OK
CMD(004): ATE0
RSP(004): ATE0
RSP(002): OK
TMO: 200 -> 5000
FLU:
TMO: 5000 -> 200
CMD(008): AT+CSCA?
RSP(026): +CSCA: "+491760000443",145
RSP(002): OK
CMD(009): AT+CMGF=0
RSP(002): OK

Danach werden langsam, im Abstand von mehreren Sekunden, die Threads zur Überwachung gestartet, jeweils ein Thread pro Server. Fehlt in der Konfiguration die Angabe der IP-Adresse, dann wird diese zuerst ermittelt.

Query IP of www.example.com...55.55.55.201
Query IP of mail.example.com...55.55.55.202

Diese Threads gehen entsprechend dem konfigurierten Wert in n_up_interval (60000 Millisekunden in unserem Beispiel) für eine Weile schlafen. Der main-Thread beginnt mit der Statusverfolgung. Wurde ein Cloudservice aktiviert, dann erfolgt bereits nach dem Start eine erste Aktualisierung. Im Terminalprogramm wird dabei nur die Antwort des Cloudservers ausgegeben. Bei ThingSpeak sieht die Antwort auf eine erfolgreiche Übermittlung in etwa so aus:

HTTP/1.1 200 OK
Server: nginx/0.8.53
Date: Thu, 20 Jun 2013 07:39:54 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: close
Vary: Accept-Encoding
Status: 200
ETag: "9abc88e0137649590b755372x040"
Cache-Control: max-age=0, private, must-revalidate
X-Rack-Cache: invalidate, pass

3
188
0
Disconnected

Entsprechend antwortet Xively mit

HTTP/1.1 200 OK
Date: Thu, 20 Jun 2013 09:09:31 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 0
Connection: close
X-Request-Id: 9264a5dcba6c8f0a77abc0f5722d08
Cache-Control: max-age=0
Vary: Accept-Encoding
Disconnected

Während der Testphase kam es bei ThingSpeak wiederholt zu Ausfällen, wobei folgende Antwort erschien:

HTTP/1.1 502 Bad Gateway
Server: nginx/0.8.53
Date: Thu, 20 Jun 2013 08:10:01 GMT
Content-Type: text/html
Connection: close
Content-Length: 383

<html>
<head>
<title>The page is temporarily unavailable</title>
<style>
body { font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body bgcolor="white" text="black">
<table width="100%" height="100%">
<tr>
<td align="center" valign="middle">
The page you are looking for is temporarily unavailable.<br/>
Please try again later.
</td>
</tr>
</table>
</body>
</html>
Disconnected

Solche Übermittlungsfehler werden übrigens nicht ausgewertet. Man kann ja auch nichts daran ändern, da das Problem beim Cloudserver liegt. Um aber keinen falschen Eindruck aufkommen zu lassen: Laut meiner Internet-Recherche galt ThingSpeak bisher als relativ zuverlässig. Entweder handelte es sich um einen unglücklichen Zufall oder die Verfügbarkeit ist kürzlich gesunken. Innerhalb der letzten 24 Stunden war Sie allerdings wenig berauschend, wie man an den fehlenden Datenpunkten sehen kann:

Der Vollständigkeit halber hier ein Diagramm von Xively:

Leider werden hier nur der Durschnittswerte dargestellt, einzelne Datenpunkte sind nicht zu erkennen. Generell läßt sich feststellen, dass das Angebot bisher untersuchter Cloudservices, zumindest der kostenlosen, relativ bescheiden ist. Für digitale Zustände sind diese garnicht ausgelegt. Die Anzeigemöglichkeiten beschränken sich auf analoge Durschnittswerte, jeweils ein einzelner Wert in einem Diagramm. Für sinnvollere Darstellungen bieten Sie aber verschiedene Schnittstellen, um die gesammelten Werte z.B. in Google Charts einzubinden oder aktuelle Zustände an Twitter zu senden.

Das Programm pollt nun die konfigurierten Server und deren Ports im Minutentakt.

Poll Internet router 192.168.1.1...up
Poll Virtual server 55.55.55.55...up
Poll www.example.com 55.55.55.201...up
Connect www.example.com:80...up
Poll mail.example.com 55.55.55.202...up
Connect mail.example.com:25...up
Connect mail.example.com:110...up
Connect mail.example.com:143...up

Etwas aktiver wird es, sobald einer der Tests fehlschlägt.

Störungsbehandlung

Das Programm versucht zuerst, eine Pingantwort vom zu überwachenden Server zu erhalten. Gelingt dies nach drei Versuchen (Standardeinstellung) nicht, dann wird ein SNMP-Trap an das konfigurierte Trap-Ziel gesendet. Da kein vollständiger SNMP-Agent implementiert ist, enthält der Trap auch keine Variable Bindings, sondern nur einen Octetstring mit dem Text der Meldung.

Ein einfacher Test kann dadurch erfolgen, dass der Netzwerkstecker am Ethernut Board abgezogen wird. Im Terminalfenster erscheint dann in etwa folgende Ausgabe:

Poll Internet router 192.168.1.1...down
Poll Virtual server 55.55.55.55...ignored
Poll www.example.com 55.55.55.201...ignored
Poll mail.example.com 55.55.55.202...ignored

Hier kann man erkennen, dass bei Ausfall es Internet-Routers die davon abhängigen Server nicht mehr gepollt werden. Wurde ein Trap-Ziel konfiguriert, erscheint außerdem:

Send trap to 192.168.1.2...OK

Da wir bei unserem Test den Ethernetstecker gezogen haben, geht dieser Trap aber verloren. Die Angabe OK bezieht sich dabei auf interne Probleme, wie fehlender Speicher usw. Ob ein Trap tatsächlich empfangen wurde, kann nicht festgestellt werden.

Während die Abfragerate in der Standardeinstellung 1 Minute beträgt, wird diese auf 10 Sekunden reduziert, sobald ein Ausfall erkannt wurde. Stecken wir den Ethernetstecker wieder zurück, sollte spätestens nach dieser Zeit der neue Zustand gemeldet werden.

Poll Internet router 192.168.192.1...up
Send trap to 192.168.1.2...OK

Der Trap wird natürlich nur gesendet, wenn das entsprechende Ziel konfiguriert ist. Da die Ethernet-Verbindung wieder hergestellt ist, kann der Trap nun auch empfangen werden. Hier ein Beispiel eines empfangenen Traps mit dem kostenlosen MIB Browser von iReasoning.

Steht die Störung länger als 2 Minuten an, wird eine SMS-Nachricht verschickt, wobei die Kommunikation mit dem GSM-Modem im Terminalfester verfolgt werden kann.

TMO: 200 -> 2000
FLU:
TMO: 2000 -> 200
CMD(010): AT+CMGS=48
TMO: 200 -> 2000
FLU: [0d][0a]>
TMO: 2000 -> 200
PDU(098): 0001000B611067854945F0ABC02853FABB2CAFABCF217119FD1697DE3A85B43C46BBCB721033EC1EBFDC2DE9BB4E2FCB15
RSP(009): +CMGS: 70
RSP(002): OK

Wenn der Mobilbetreiber nicht gerade überlastet ist, sollte die Meldung innerhalb weniger Sekunden auf dem Handy erscheinen. Übrigens, die meisten Provider erlauben den Versand von SMS an gewöhnliche Festnetztelefone. Der Text wird dann von einer synthetisch erzeugten Stimme vorgelesen.

Weitere Möglichkeiten

Diese sind praktisch unerschöpflich. Falls sich das Ethernut Board im gleichen Schrank wie die zu überwachenden Server befindet, könnte man zusätzlich ein CMI8848 Add-On verwenden, um bei Ausfall einer Komponente einen automatischen Hardware-Reset auszulösen, ggf. nach Empfang einer entsprechenden SMS-Nachricht. Oder man verwendet die SMTP-Aufrufe von Nut/OS um neben der SMS auch eine Email zu verschicken.

Neben dem praktischen Nutzen dieser Beispielanwendung, lassen sich Teile davon in eigene Anwendungen übernehmen. Speziell die Anbindung an einen Cloudserver eignet sich zur Archivierung verschiedener Messdaten. Aber auch das Versenden von Störmeldungen als SNMP-Trap oder SMS-Nachricht kann den Nutzen einer Applikation entscheidend verbessern.

Castrop-Rauxel, den 20.06.2013