Nacht

 

Die Entwicklung beim FHEM geht recht rege voran, Updates gibt's praktisch jeden Tag. Ich hole mir ständig die aktuellsten Sourcen. So hat man schnell die neuen Funktionen und Fehlerfixes. Als Kehrseite der Aktualität erkauft man den Nachteil der Instabilität. Auch wenn der Server meist sehr stabil läuft, kann es schon mal passieren, dass er mal abstürzt oder 'hängen' bleibt. In den letzten 6 Monaten hatte ich solche Situationen schon paar Mal.

Es ist an sich nicht sehr schlimm, wenn der Server kurzfristig nicht funktioniert, ein Dauerausfall ist aber schon unangenehm. Und so beschloss ich ein Watchdog-Script zu schreiben, der den Zustand des FHEM-Servers überwacht und ihn bei Bedarf neustartet.

Die Funktionsweise ist einfach. Es wird regelmäßig geprüft, wie viel Zeit seit dem letzten Lebenszeichen des Servers vergangen ist. Bei Überschreitung eines definierten Maximums wird die laufende Instanz beendet und eine neue gestartet.

Das 'Lebenszeichen' wird durch die Protokollierung des Zustandes eines extra dafür angelegtes Objektes erzeugt. Folgende Auszug aus fhem.cfg stellt die Definitionen des Objektes, der zugehörigen Log-Datei und der Routine zur periodischen Aktualisierung des Zustandes dar. Zur Vusualisierung wird ein Diagramm (WebLink) definiert. Damit auch die Log-Ausgabe des Watchdogscriptes im FHEM angesehen werden kann, wird diese Logdatei als eine Externe-Logdatei definiert (fakelog).

...
# Definition eines Dummy-Objektes fuer 'Alive'-Meldungen
define NN_TE_DMST01.Server_Heartbeat dummy attr NN_TE_DMST01.Server_Heartbeat group Watchdog attr NN_TE_DMST01.Server_Heartbeat room 9.03_Tech # Protokoliert Zeitpunkt der letzten Änderung (in Objekt-Eigenshaften)
attr NN_TE_DMST01.Server_Heartbeat userReadings lastChange { CurrentTime() }
# Definition der Log-Datei
define FileLog_NN_TE_DMST01.Server_Heartbeat FileLog ./log/NN_TE_DMST01.Server_Heartbeat-%Y-%m.log NN_TE_DMST01.Server_Heartbeat attr FileLog_NN_TE_DMST01.Server_Heartbeat group Watchdog attr FileLog_NN_TE_DMST01.Server_Heartbeat logtype myServerHeartbeat:Plot,text attr FileLog_NN_TE_DMST01.Server_Heartbeat room 9.03_Tech
# Visualisierung mittels eines Diagramms
define 0.wlHeartbeat SVG FileLog_NN_TE_DMST01.Server_Heartbeat:myServerHeartbeat:CURRENT
attr 0.wlHeartbeat group Watchdog
attr 0.wlHeartbeat room 9.03_Tech

# Routine zur regelmaessigen Änderungen des Wertes des Dummy-Objektes
define tickHeartbeat at +*00:01:00 {tickHeartbeat('NN_TE_DMST01.Server_Heartbeat');;} attr tickHeartbeat alignTime 00:00 attr tickHeartbeat group Watchdog attr tickHeartbeat room 9.03_Tech
# Log-Datei des Watchdogscriptes verfügbar machen
define FileLog_wathdog FileLog ./log/watchdog.log fakelog
attr FileLog_wathdog group Watchdog
attr FileLog_wathdog room 9.03_Tech

# Visualisierung für Watchdog-Log
define 0.wlWatchdog SVG FileLog_wathdog:myWatchdog:CURRENT
attr 0.wlWatchdog group Watchdog
attr 0.wlWatchdog room 9.03_Tech
...

 

Das Diagramm hilft ein schnelles Überblick über die möglichen Ausfälle in der letzten Zeit zu beschaffen. Dazu wird folgende Plot-Datei verwendet (myServerHeartbeat.gplot):

# Plot fuer Visualisierung von Server-Hearbeat-log
set terminal png transparent size  crop
set output '.png'
set title ''
set xdata time
set timefmt "%Y-%m-%d_%H:%M:%S"
set xlabel " "
set grid xtics y2tics
set ytics ("" 0, "" 30, "" 59)
set ylabel ""
set yrange [-1:60]
set y2tics ("" 0, "" 30, "" 59)
set y2label ""
set y2range [-1:60]
#FileLog 3:
plot "" x1y1 notitle ls l1fill lw 0.5 with steps

 

Auch für die Daten aus dem Watchdog-Log habe ich eine entsprechende Visualisierung entwickelt. Da kann abgelesen werden, wie die 'Heartbeat'-Zeiten waren und wann ggf. ein Ausfall registriert wurde.

#
# Anzeige der Watchdog-Log-Informationen
#
set terminal png transparent size  crop
set output '.png'
set xdata time
set timefmt "%Y-%m-%d_%H:%M:%S"
set xlabel " "
set title 'Watchdog'
set yrange [-10:300]
set y2label "Zeit (s)"
set ytics ("alive" 0, "dead" 1)
set yrange [-0.1:1.1]
set ylabel "Status"
#FileLog 4:\x20V\x3a:0:
#FileLog 6:\x20S\x3a:0:$fld[5]=~"dead"?1:0
plot "" x1y2 notitle ls l5 lw 0.5 with steps, \
            x1y1 notitle ls l8fill lw 0 with steps

 

Es sieht dann in etwa so aus (die beiden Ausfälle wurden hauptsächlich durch meine eigenen Basteleien verursacht):

 

In den Scripten oben wurden zwei Methoden verwendet, die in der Datei '99_myUtils.pm' abgelegt sind:

...
# --- Liefert aktueller Zeitstempel ---
sub CurrentTime()
{
  return strftime("%H:%M:%S", localtime());
}
# --- server heartbeat / watchdog ---
sub tickHeartbeat($)
{
    my ($device) = @_;
    my $v = int(Value($device));
    $v = $v+1;
    if($v>=60) {$v=0;}
    fhem("set $device $v");
}
...

 

 Als nächstens muss der eigentliche Überwachung-Script her. Was dabei herausgekommen ist, kann bei GitHub angesehen werden (watchdogloop.sh)

Ein Starter-Script prüft vor dem Start der Überwachungsroutine, ob eine Instanz davon bereits aktiv ist (runwatchdog.sh).

Damit Watchdog austomatisch anläuft, muss beim Starten von FHEM auch der Watchdog mitgestartet werden. Dafür wird in der Startdatei (startfhem) eine entsprechende Anweisung eingefügt.

Folgendes Script habe ich vollständigkeitshalber erstellt. Damit wird der Watchdog beendet.

#!/bin/sh
killall watchdogloop.sh

 

Anmerkungen:

Da bei einem Update der FEHM-Server nicht reagiert, muss der Watchdog vor dem Update deaktiviert werden. Ansonsten kann es passieren, dass das laufende Update gewaltsam unterbrochen wird. Eine andere Möglichkeit ist, die Update im Hintergrund durchführen zu lassen. Das geschieht durch ein Attribut (attr global updateInBackground 1) in fhem.cfg. Dabei wird der Server während des Update-Prozesses nicht (mehr) blockiert.

Zuletzt habe ich noch das eigentliche Start-Script /etc/init.d/fhem umgebogen (bei GitHub unter: etc_init.d_fhem_script.txt). Zum Starten/Stoppen werden jetzt startfhem bzw. stopfhem werdendet.

 

Links

Die letzten Versionen sind bei GitHub zu finden:

https://github.com/hexenmeister/MyFHEM/blob/master/watchdogloop.sh
https://github.com/hexenmeister/MyFHEM/blob/master/runwatchdog.sh
https://github.com/hexenmeister/MyFHEM/blob/master/killwatchdog.sh
https://github.com/hexenmeister/MyFHEM/blob/master/startfhem
https://github.com/hexenmeister/MyFHEM/blob/master/stopfhem
https://github.com/hexenmeister/MyFHEM/blob/master/FHEM/99_myUtils.pm

https://github.com/hexenmeister/MyFHEM/blob/master/www/gplot/myServerHeartbeat.gplot
https://github.com/hexenmeister/MyFHEM/blob/master/www/gplot/myWatchdog.gplot

https://github.com/hexenmeister/MyFHEM/blob/master/etc_init.d_fhem_script.txt

 

Update:

Ich habe den Benutzer fhem in die Gruppe sudo aufgenommen. Damit will ich sicherstellen, dass der Script in der Lage ist, volle Kontrolle über den FHEM-Server auszuüben, auch dann, wenn dieser unter einem anderen Benutzeraccount gestartet sein sollte.

sudo usermod -aG sudo fhem

Um keine Sicherheitslücke aufzumachen, bekommt dieser Benutzer Rechte zur Ausführung mit sudo nur für ganz bestimmte Scripte. Dies geschieht durch Einfügen einer Zeile in die Datei sudoers (sudo nano /etc/sudoers).

fhem ALL=(ALL) NOPASSWD: /opt/fhem/runwatchdog.sh, /opt/fhem/killwatchdog.sh, /opt/fhem/watchdogloop.sh, /opt/fhem/runfhem.sh, /opt/fhem/killfhem.sh

 

 

Kommentare (2)

Cancel or

  • Alexander
    @Miro
    Hallo Miro,

    Wenn FHEM-Part funktioniert, müssen nur noch die Bash-Scripte kopiert und aktiviert werden.
    Ich hatte schon ähnliche Frage im Forum bekommen. Hier:
    http://forum.fhem.de/index.php/topic,17221.msg112845.html#msg112845
    Da ist etwas genauer beschrieben, was wohin gehört.

    Grüße,

    Alexander
  • Miro
    Danke für die gute Idee. Nach sowas habe ich schon lange gesucht. :)
    Ich habe deine Anleitung bis zum Überwachung-Script ausgeführt und die Diagramme werden mir richtig angezeigt. Leider weiß ich nicht wie ich dann weiter fortfahren muss. Wo muss das Überwachung-Script selbst abgelegt werden? Und wie führt man die weiteren Schritte aus?

    Danke!