FHEM über systemd mit Watchdog und sd_notify

Begonnen von a-p-s, 03 März 2018, 23:05:27

Vorheriges Thema - Nächstes Thema

a-p-s

Hallo zusammen,

aufbauend auf den Diskussionen hier zum Thema systemd hatte ich ein paar Experimente gemacht, um meine FHEM-Installationen etwas stabiler zu machen, ohne die Komplexität hochzuschrauben. Dafür habe ich die systemd-Bordmittel (Watchdog) genutzt.

Hier die resultierende Service Unit:


[Unit]
Description=FHEM Home Automation
Requires=network.target
After=dhcpcd.service

[Service]
Type=notify
NotifyAccess=all
User=fhem
Group=dialout
WorkingDirectory=/opt/fhem
ExecStart=/usr/bin/perl fhem.pl fhem.cfg
TimeoutStartSec=240
TimeoutStopSec=120
ExecStop=/usr/bin/pkill -U fhem perl
Restart=always
RestartSec=10
WatchdogSec=180
PIDFile=/opt/fhem/log/fhem.pid

[Install]
WantedBy=multi-user.target


Um den Watchdog zu nutzen, muss man aus FHEM regelmäßige Nachrichten über ein UNIX-Socket schicken (sd_notify). Da die Bibliotheken, die ich gefunden habe, ultra-heavy sind für den simplen Task, ist das hier schnell zusammengeschrieben:


attr global nofork 1

defmod systemd_ready notify global:INITIALIZED { \
use Socket;;;;\
my $name = $ENV{NOTIFY_SOCKET};;;;\
my $sock_addr = sockaddr_un($name);;;;\
socket(my $server, PF_UNIX,SOCK_DGRAM,0);;;;\
connect($server, $sock_addr);;;;\
print $server "READY=1\n";;;;\
close($server);;;; }

defmod systemd_shutdown notify global:SHUTDOWN {\
use Socket;;;;\
my $name = $ENV{NOTIFY_SOCKET};;;;\
my $sock_addr = sockaddr_un($name);;;;\
socket(my $server, PF_UNIX,SOCK_DGRAM,0);;;;\
connect($server, $sock_addr);;;;\
print $server "STOPPING=1\n";;;;\
close($server);;;; }

defmod systemd_watchdog at +*00:01 { \
use Socket;;;;\
my $name = $ENV{NOTIFY_SOCKET};;;;\
my $sock_addr = sockaddr_un($name);;;;\
socket(my $server, PF_UNIX,SOCK_DGRAM,0);;;;\
connect($server, $sock_addr);;;;\
print $server "WATCHDOG=1\n";;;;\
close($server);;;; }


Das funktioniert bei mir seit einer Weile ganz gut. Mit den Timeouts muss man ein bisschen spielen. Eine meiner Installationen ist da (zeitweise) etwas träge, so dass ich die Timeouts hochgesetzt habe.

Momentan ist das noch ein Hack - da kann man ein Modul draus bauen.

Vielleicht kann trotzdem jemand etwas damit anfangen.

Grüße,
a-p-s

hexenmeister

Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

#2
So, hier wäre das. Richtig testen konnte ich noch nicht, muss zuerst mein Test-FHEM auf systemd-script umstellen.
Datei in FHEM-Verzeichnis werfen und Device anlegen.
define watchdog systemd_watchdog

EDIT: Anhang gelöscht
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

#3
Habe ein Fehler mit dem InternalTimer gefunden (lief nach dem Löschen von Modul, mit aktivierten Watchdog sollte man das Modul eh jedoch besser nicht löschen).
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

Vorerst endgültige Version (nur Commandref geschrieben).
Habe zwischendurch testen können.  Benutze Type=forking mit einer PIDFile. Funktioniert bis jetzt sehr gut. Shutdown klappt (Restart=allways durch Restart=on-failure ersetzt). Nach dem kill -9 wird korrekt neu gestartet.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

a-p-s

Das ging ja super schnell. Danke!

Habe meine Bastellösung durch das Modul ausgetauscht (blieb also bei Type=Notify). Funktioniert bislang einwandfrei.

Grüße,
a-p-s

hexenmeister

Zitat von: a-p-s am 04 März 2018, 20:11:12
Das ging ja super schnell. Danke!
Gerne. Deine Bastellösung ersparte mir die Suche und Einarbeitung um meine Bastellösung zu ersetzen. win-win ;)
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

#7
Kurzanleitung für die Verwendung:


  • Sicherstellen, dass das eigene System unter Kontrolle von Systemd läuft. Dürfte bei den meisten aktuellen Linux-Distributionen der Fall sein.
  • Datei 98_systemd_watchdog.pm in das FHEM-Modulverzeichnis kopieren. Link: https://raw.githubusercontent.com/hexenmeister/MyFHEM/master/FHEM/98_systemd_watchdog.pm
  • In FHEM Watchdog-Device erstellen: define watchdog systemd_watchdog
  • Bleibt es bei Type=forking, dann sicherstellen, dass FHEM eine PID-Datei schreibt. Ggf. global Attribute pidfilename seiten: attr global pidfilename /opt/fhem/log/fhem.pid
    Bei Type=notify muss nofork=1 gesetzt werden: attr global nofork 1
  • FHEM beenden, falls noch läuft.
  • Sicherstellen, dass FHEM mittels systemd-script gestartet wird. Ggf. noch vorhandenen init.d-Script entfernen.
  • Systemd-Script (Inhalt s.u.) erstellen: sudo nano /etc/systemd/system/fhem.service
  • Systemd-Konfiguration aktualisieren: sudo systemctl daemon-reload
  • FHEM starten: sudo systemctl start fhem.service
  • Prüfen, ob alles wie gewünscht funktioniert: FHEM wird nicht alle 3 Minuten durch den Watchdog gekillt, beim Beenden mittels kill -9 wird neu gestartet, bei shutdown (aus FHEM) jedoch nicht.



[Unit]
Description=FHEM Home Automation
Requires=network.target
#After=network.target
After=dhcpcd.service

[Service]
Type=forking
NotifyAccess=all
User=fhem
Group=dialout
WorkingDirectory=/opt/fhem
ExecStart=/usr/bin/perl fhem.pl fhem.cfg
#ExecStart=/usr/bin/perl fhem.pl configDB
TimeoutStartSec=240
TimeoutStopSec=120
#ExecStop=/usr/bin/pkill -U fhem perl
ExecStop=/usr/bin/pkill -f -U fhem "fhem.pl fhem.cfg"
# Restart options: no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, or always.
Restart=on-failure
RestartSec=3
WatchdogSec=180
PIDFile=/opt/fhem/log/fhem.pid

[Install]
WantedBy=multi-user.target


Das Modul erzeugt zwei Readings:
state: gibt an, ob die Instanz aktiv ist (ist automatish der Fall, wenn Systemd-Watchdog verfügbar ist)
next: zeigt den Zeitpunkt der nächten keep-alive-Meldung

Außerdem gibt es zusützlich zu den allgemeinen 'Internals' zwei weitere:
sleep-time: Zeitinterval zw. den keep-alive-Meldungen (wird aus dem im Watchdog definierten Interval ausgerechnet, es wird ein Vietel von der maximalen Zeit verwendet).
systemd-watchdog: zeigt an, ob Systemd-Watchdog verfügbar ist.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

Habe jetzt das Modul ein paar Tage getestet, für stabil befunden und letztendlich in contib eingecheckt.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

tpm88

Hallo Alexander,

Zitat von: hexenmeister am 04 März 2018, 21:21:31
Kurzanleitung für die Verwendung:


  • Prüfen, ob alles wie gewünscht funktioniert: FHEM wird nicht alle 3 Minuten durch den Watchdog gekillt, beim Beenden mittels kill -9 wird neu gestartet, bei shutdown (aus FHEM) jedoch nicht.


Ich habe den watchdog exakt nach obiger Kurzanleitung definiert.

Er funktioniert soweit einwandfrei - allerdings wird fhem auch bei einem shutdown (aus FHEM) neu gestartet - trotz:
Restart=on-failure

Hier ein paar relevante Zeilen aus dem fhem.log:


2018.03.15 22:40:31 0: Server shutdown
2018.03.15 22:40:31 1: Timeout for SIP_ListenStart reached, terminated process 30235
2018.03.15 22:40:31 2: Watchdog Client: Shutting down
2018.03.15 22:40:31 2: Watchdog Client: deactivated
2018.03.15 22:40:35 3: [UtilsHourCounter] Init Done with Version 1.0.1.0 - 10.12.2014 (john)
2018.03.15 22:40:36 1: PERL WARNING: "my" variable $url masks earlier declaration in same scope at ./FHEM/99_myUtils.pm line 371.
2018.03.15 22:40:36 1: Including fhem.cfg
2018.03.15 22:40:36 3: telnetPort: port 7072 opened
...
2018.03.15 22:40:53 2: Watchdog Client: initialized
2018.03.15 22:40:53 3: OWS_rpi1: Opening connection to OWServer 192.168.8.52:4304...
2018.03.15 22:40:53 3: OWS_rpi1: Successfully connected to 192.168.8.52:4304.
2018.03.15 22:40:54 1: PERL WARNING: Use of uninitialized value in split at ./FHEM/10_OWServer.pm line 395.
2018.03.15 22:40:54 0: [Freezemon] fm: Log3 is already wrapped
2018.03.15 22:40:54 0: [Freezemon] fm: status=already wrapped
2018.03.15 22:40:54 2: [Freezemon] fm ready to watch out for delays greater than 1 second(s)
2018.03.15 22:40:54 3: NTFY return:  watchdog:active
2018.03.15 22:40:54 0: Featurelevel: 5.8
2018.03.15 22:40:54 0: Server started with 201 defined entities (fhem.pl:16403/2018-03-13 perl:5.020002 os:linux user:fhem pid:30427)


Hast du eine Idee?

Gruß
Tobias
Test FHEM Server on RPi, CUL_HM
Prod FHEM Server on Odroid HC1, HM-USB, JeeLink
Devices: diverse HM, IT1500, 1wire, LaCrosse, MQTT

hexenmeister

Ich weiß nicht, was ich damals getestet habe ??? War wohl schon zu spät... Wie auch immer, jetzt tut es bei mir auch nicht - es startet immer neu. Möglicherweise liefert FHEM nie den Wert für 'efolgreich beendet' zurück. Muss ich mir mal genauer ansehen.
>:(
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

Funsailor

Hallo Alexander,
ist der von tpm88 gemeldete Fehler mit dem shutdown mit deiner Version
17206 2018-08-25 18:18:49
gefixt?
- Asus PN 41- mapleCul V1.24.01 - FHEMDuino - FHEM 6.2 - HUE Bridge - ESPEasy Bridge -  Milight HUB - smartVISU 3.40 -

hexenmeister

Der Fehler bezieht sich noicht auf das Modul, das funktioniert richtig. Der systemd-Script müsste irgendwie angepasst werden, da bin ich jedoch kein Experte. Für meine Zwecke ist es nur wichtig, dass es sicher neugestartet wird. Wenn jemand eine Lösung hat, werde ich sie entsprechend im Commandref beschreiben.
Derzeit funktioniert es bei mir genau andersrum: 'shutdown' bewirkt einen Restart und 'shutdown restart' beendet FHEM.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

Funsailor

Hallo Alexander,
ich habe den Wdt gestern nach deiner Anleitung eingebaut (vorher hatte ich schon auf Systemctl.umgestellt, das lief gut durch)
Wenn ich in global norfork =>1 setze, fährt mir fhem regelmäßig herunter. Angeblich sendet mein (in der Liste erstes) fronthem device ein Shutdown....
Muss bei Gelegenheit weitersuchen, bin jetzt unterwegs. Aber falls jemand eine Idee hat..... wäre gut.
Danke....
- Asus PN 41- mapleCul V1.24.01 - FHEMDuino - FHEM 6.2 - HUE Bridge - ESPEasy Bridge -  Milight HUB - smartVISU 3.40 -

Gisbert

#14
Hallo Alexander, Funsailor und a-p-s,

gibt es einen Fortschritt in dieser Sache? Ich wäre interessiert es einzusetzen.
Ich möchte gerne eine stabile Lösung, die ich mit meinen laienhaften Kenntnissen umsetzen kann.

Meine Erfahrungen mit unterschiedlichen Ansätzen zum Neustart von Fhem und/oder des Servers sind ernüchternd, es ist nicht auszuschließen, dass es an mir lag:
- Einen Neustart habe ich bisher nicht wissentlich registriert.
- Dafür war die Überwachung selbst zweimal die Ursache, warum entweder Fhem nicht mehr gestartet werden konnte oder den Server im Minutentakt neu gestartet hat.

Folgender Weg über systemd mit Watchdog funktioniert leider nicht.
Auszug Service Unit:
WatchdogSec=120s
StartLimitInterval=5min
StartLimitBurst=4
StartLimitAction=reboot-force

Definition in Fhem:
defmod heartbeat at +*00:01:00 {qx(systemd-notify WATCHDOG=1)}
Ergebnis ist, dass Fhem alle 120 Sekunden neu gestartet wird - d.h. an und für sich geht der Watchdog.
Allerdings macht der Befehl in Fhem nichts sinnvolles, nämlich einen Neustart von Fhem zu verhindern, wenn es noch läuft.

Viele Grüße Gisbert
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY