Fhem.service (systemd unit file): Unterschied zwischen den Versionen
(→Start verzögern: TimeoutStartSec= eingefügt) |
|||
Zeile 143: | Zeile 143: | ||
Es ist immer besser eine direkte Abhängigkeit zu definieren. In unklaren Situationen oder als erste Abhilfe kann es notwendig sein, einfach den FHEM Start zu verzögern. | Es ist immer besser eine direkte Abhängigkeit zu definieren. In unklaren Situationen oder als erste Abhilfe kann es notwendig sein, einfach den FHEM Start zu verzögern. | ||
Der default Wert für ''TimeoutStartSec='' liegt bei 90 sec. Soll die Startverzögerung länger sein, muss dieser Wert zusätzlich gesetzt werden. Ansonsten wird der Start mit einer Fehlermeldung abgebrochen. | Der default Wert für ''TimeoutStartSec='' liegt bei 90 sec. Anzeige mit <code>systemctl show fhem.service -p TimeoutStartUSec</code> | ||
Soll die Startverzögerung länger sein, muss dieser Wert zusätzlich gesetzt werden. Ansonsten wird der Start mit einer Fehlermeldung abgebrochen. | |||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
[Service] | [Service] |
Version vom 6. Februar 2022, 12:07 Uhr
Die Datei fhem.service ist ein systemd unit file und wird bei der debian Installation von FHEM mit ausgeliefert. Änderungen an dieser Datei sind normalerweise nicht notwendig. Man sollte zumindest genau wissen was man tut! Der Artikel soll die Datei etwas beschreiben und ein paar Fälle behandeln die ein Anpassung notwendig machen.
Unit File - ein paar kurze Erklärung
Den aktuellen Inhalt kann man jederzeit anschauen:
systemctl cat fhem
Stand Mai 2020 hat die Datei folgenden Inhalt:
Inhalt /etc/systemd/system/fhem.service
# $Id: fhem.service 19235 2019-04-21 13:26:17Z betateilchen $
[Unit]
Description=FHEM Home Automation
Wants=network.target
After=network.target
#Requires=postgresql.service
#After=postgresql.service
#Requires=mysql.service
#After=mysql.service
[Service]
Type=forking
User=fhem
Group=dialout
WorkingDirectory=/opt/fhem
ExecStart=/usr/bin/perl fhem.pl fhem.cfg
#ExecStart=/usr/bin/perl fhem.pl configDB
Restart=always
[Install]
WantedBy=multi-user.target
Erklärung ausgewählter Parameter
Wants= die angegebene Services werden benötigt, fhem startet aber trotzdem falls die Services nicht gestartet werden können.
Requires= wenn der Service nicht gestartet werden kann, wird fhem nicht gestartet.
After= bewirkt, dass fhem nach dem Service (der Gruppe) gestartet wird.
Das ist wichtig damit Services die für fhem notwendig sind schon gestartet sind. Benötig fhem z.B. Datenbanken sind die entsprechenden Zeilen einzubauen oder durch entfernen des Kommentarzeichens (#) zu aktivieren.
User=fhem bewirkt das der Services mit user fhem gestartet wird. Falls fhem mit dem user root gestartet wird, startet fhem.pl einen neuen Prozess unter dem User fhem.
Group=dialout Es wird die Gruppe dialout zum Start benutzt.
Beide Zeilen können für den normalen Start von FHEM auch auskommentiert werden.
Zusätzlicher Parameter
ExecStartPre= Hier kann ein Shell Befehl stehen, der vor dem Start des eigentlichen Service (ExecStart=) ausgeführt wird.
unit file bearbeiten
Dieser Befehl editiert die (fhem.service) unit Datei mit dem Standard Editor (z.B. nano) und führt zum Abschluss auch ein daemon-reload durch.
sudo systemctl edit --full fhem
Tipp: Datei speichern ctrl+s und Editor verlassen ctrl+x
Prozesse vor dem FHEM Start ausführen
Ziel ist es sicherzustellen, dass für den Start von FHEM alle Voraussetzungen erfüllt sind, z.B.
- Hardware aktiviert (COC, FHEM_auf_Raspberry_PI_mit_COC_betreiben, SCC Busware, HM-CFG-USB)
- Datenbank gestartet
- Systemprozess läuft (z.B. Bluetooth gestartet
- eigenen Prozessen ist gestartet
- Sprache einstellen
Dazu gibt es mehrere Lösungswege:
- die Datei fhem.service modifizieren
- einen separaten Service implementieren
- Abhängigkeiten definieren
Ein Script mit separater service unit starten
Wir erstellen quasi einen eigenen Service - Vorteil: Die fhem.service braucht man nicht verändern.
1. Script bereitstellen
Das Beispiel hier in einem allgemeinerem Pfad:
sudo nano /user/local/bin/EnableXX.sh
Den Code (Beispiele am Ende) hier einfügen und die Datei speichern und Editor verlassen (ctrl+s ctrl+x).
Hier kann meist der Original Scriptcode verwendet werden, der früher in das init.d Script eingefügt werden sollte.
2. unit file erzeugen
Man erstellt eine neues unit file.
sudo systemctl edit --full --force enablexx.service
Mit folgendem Inhalt
[Unit]
Description=EnableXX
Before=fhem.service
#After=network.target
[Service]
Type=oneshot
ExecStart=bash /user/local/bin/EnableXX.sh
StandardOutput=journal
[Install]
WantedBy=multi-user.target
Die Zeile Before=fhem.service stellt sicher, dass der Start vor FHEM erfolgt. 3. Service aktivieren
#sudo systemctl daemon-reload # nur notwendig wenn nicht systemctl edit verwendet wurde
sudo systemctl enable enablexx
sudo systemctl start enablexx
Den Erfolg auch nach einem komplette Neustart testen!
Ein Script zusammen mit FHEM starten
1. Script bereitstellen
Dazu wird eine Scriptdatei erzeugt, Beispiel:
sudo nano /opt/fhem/ExecStartPre.sh
Den Code (Beispiele am Ende) hier einfügen und die Datei speichern und Editor verlassen (ctrl+s ctrl+x).
2. ExecStartPre aktivieren
Um ein Script mit root Rechten in der fhem.service unit auszuführen, müssen drei Zeilen in der Datei geändert werden (siehe oben).
Vor der Zeile ExecStart= wir diese Zeile eingefügt:
[Service]
...
ExecStartPre= bash /opt/fhem/ExecStartPre.sh
ExecStart=...
Die beiden Zeilen User und Group muss man auskommentieren, da die Unit sonst mit dem User fhem ausgeführt wird.
#User=fhem #Group=dialout
3. Änderungen aktivieren
Die Änderungen werden erst nach einem daemon-reload aktiv und nach einem restart wirksam.
#sudo systemctl daemon-reload # nur notwendig wenn nicht systemctl edit verwendet wurde
sudo systemctl restart fhem
Den Erfolg auch nach einem komplette Neustart testen!
Start von anderen Services abhängig machen
In der fhem.service unit kann man sicherstellen, dass ein Service fertig gestartet wurde bevor fhem startet. Dazu kann man im unit Abschnitt zwei Zeilen einfügen (bzw. Kommentar entfernen):
Wants=xxx.service
After=xxx.service
Man kann auch erzwingen, dass FHEM nicht startet falls die Voraussetzungen nicht erfüllt sind. Dafür muss anstatt Wants= Requires= verwendet werden.
Einstellungen dies und das
Start verzögern
Es ist immer besser eine direkte Abhängigkeit zu definieren. In unklaren Situationen oder als erste Abhilfe kann es notwendig sein, einfach den FHEM Start zu verzögern.
Der default Wert für TimeoutStartSec= liegt bei 90 sec. Anzeige mit systemctl show fhem.service -p TimeoutStartUSec
Soll die Startverzögerung länger sein, muss dieser Wert zusätzlich gesetzt werden. Ansonsten wird der Start mit einer Fehlermeldung abgebrochen.
[Service]
...
ExecStartPre=/bin/sleep 10
#TimeoutStartSec= # default 90, set for larger sleep time
Restart verzögern
Sollte man z.B. bei einem Neustart über die FHEM Oberfläche (shutdown restart) zwei Starts innerhalb von 1 Sekunde im Logfile beobachten, kann man den Neustart im unit file mit einem Parameter um 2 - 10 Sekunden (siehe auch diesen Forenbeitrag) verzögern:
[Service]
...
Restart=...
RestartSec=2
...
Hinweise und Tipps
Startreihenfolge beeinflussen
Wie man erzwingen kann, dass FHEM nach hciuart (Bluetooth Service) startet, ist in diesem Forenbeitrag beschrieben.
Ausgaben im Script
Ausgaben mit echo landen im /var/log/syslog. Das Log kann man mit diesem Befehl anzeigen. Ist das Logfile zu unübersichtlich kann man sich auch z.B. nur 15 Zeilen nach systemd Ausgabe des unit files anzeigen lassen.
cat /var/log/syslog
cat /var/log/syslog|grep -A 15 "FHEM Home"
Beispielcode
Diese Codebeispiel ist auf dem Raspberry Pi ausführbar und lässt vor dem Start von FHEM die grüne LED (ACT) blinken.
Beispiel 1: 3 mal kurz und 3 mal lang
# Lass die ACT LED (grün) am Pi 3 mal kurz und 3 mal lang blinken
ANZAHL=3
#Status (Standard [mmc0] )sichern
trigger=$(cat /sys/class/leds/led0/trigger|grep -o "\[.*\]"|tr -d [+])
#umschalten auf manuell
echo "none" >/sys/class/leds/led0/trigger
#blinken
for ((i=1 ; i<=$(( $ANZAHL * 2 )) ; i++ )); do
echo $(( $i % 2 )) >/sys/class/leds/led0/brightness
sleep 0.3
done
for ((i=1 ; i<=$(( $ANZAHL * 2 )) ; i++ )); do
echo $(( $i % 2 )) >/sys/class/leds/led0/brightness
sleep 1
done
#Status wieder herstellen
echo $trigger >/sys/class/leds/led0/trigger