Gelöst! Shell Skript für systemd Überwachung

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 08.03.2018 00:49:53

Wenn ich dich richtig verstehe, dann sollte das Verhalten von OnFailure so sein, dass der Service z.B. 5 Mal erfolglos gestartet wird, dann fällt die Unit in den "Failed"-Zustand, und dann wird "OnFailure" ausgelöst. So würd ich die Manpage verstehen.

Ich hab mir jetzt einmal diese Test-Unit gebaut:

Bau dir einmal diese Test-Unit:

Code: Alles auswählen

/etc/systemd/system: # cat test@.service 
[Unit]
Description=Testservice notification
OnFailure=notification-telegram-failed@%n.service

[Service]
Type=simple
Restart=on-failure
#RestartSec=10
ExecStart=/bin/%i
SyslogIdentifier=test@%i.service
StartLimitBurst=5
StartLimitInterval=10
Und die telegram-notification-Unit so vereinfacht:

Code: Alles auswählen

# cat notification-telegram@.service 
[Unit]
Description=Send failure-notification about %i to telegram

[Service]
User=jakob
ExecStart=/bin/bash -c "/usr/local/bin/ntfy -b telegram send \"FAILED\n$(systemctl status %i)\""
Wenn ich mit

Code: Alles auswählen

systemctl start test@false
die testunit aufrufe, sodass ExecStart=/bin/false ausgeführt wird und das journal beobachte, so wird die Unit 5 Mal neu gestartet und fällt dann in den Failed-Zustand:

Mär 08 00:31:53 aldebaran systemd[1]: Started Testservice notification.
Mär 08 00:31:53 aldebaran systemd[1]: test@false.service: Main process exited, code=exited, status=1/FAILURE
Mär 08 00:31:53 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:31:53 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Service hold-off time over, scheduling restart.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Scheduled restart job, restart counter is at 1.
Mär 08 00:31:54 aldebaran systemd[1]: Stopped Testservice notification.
Mär 08 00:31:54 aldebaran systemd[1]: Started Testservice notification.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Main process exited, code=exited, status=1/FAILURE
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Service hold-off time over, scheduling restart.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Scheduled restart job, restart counter is at 2.
Mär 08 00:31:54 aldebaran systemd[1]: Stopped Testservice notification.
Mär 08 00:31:54 aldebaran systemd[1]: Started Testservice notification.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Main process exited, code=exited, status=1/FAILURE
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Service hold-off time over, scheduling restart.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Scheduled restart job, restart counter is at 3.
Mär 08 00:31:54 aldebaran systemd[1]: Stopped Testservice notification.
Mär 08 00:31:54 aldebaran systemd[1]: Started Testservice notification.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Main process exited, code=exited, status=1/FAILURE
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Service hold-off time over, scheduling restart.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Scheduled restart job, restart counter is at 4.
Mär 08 00:31:54 aldebaran systemd[1]: Stopped Testservice notification.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Start request repeated too quickly.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:31:54 aldebaran systemd[1]: Failed to start Testservice notification.
Mär 08 00:31:54 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.


Ich bekomme 3 Notifications. Wahrscheinlich, weil die notification-Unit zu oft hintereinander aufgerufen wird, und der sendeprozess noch nicht abgeschlssen ist.

Daher hab ich RestartSec=2 einkommentiert und noch einmal ausgeführt:


Mär 08 00:44:14 aldebaran systemd[1]: Started Testservice notification.
Mär 08 00:44:14 aldebaran systemd[1]: test@false.service: Main process exited, code=exited, status=1/FAILURE
Mär 08 00:44:14 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:44:14 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.
Mär 08 00:44:16 aldebaran systemd[1]: test@false.service: Service hold-off time over, scheduling restart.
Mär 08 00:44:16 aldebaran systemd[1]: test@false.service: Scheduled restart job, restart counter is at 1.
Mär 08 00:44:16 aldebaran systemd[1]: Stopped Testservice notification.
Mär 08 00:44:16 aldebaran systemd[1]: Started Testservice notification.
Mär 08 00:44:16 aldebaran systemd[1]: test@false.service: Main process exited, code=exited, status=1/FAILURE
Mär 08 00:44:16 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:44:16 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.
Mär 08 00:44:19 aldebaran systemd[1]: test@false.service: Service hold-off time over, scheduling restart.
Mär 08 00:44:19 aldebaran systemd[1]: test@false.service: Scheduled restart job, restart counter is at 2.
Mär 08 00:44:19 aldebaran systemd[1]: Stopped Testservice notification.
Mär 08 00:44:19 aldebaran systemd[1]: Started Testservice notification.
Mär 08 00:44:19 aldebaran systemd[1]: test@false.service: Main process exited, code=exited, status=1/FAILURE
Mär 08 00:44:19 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:44:19 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.
Mär 08 00:44:21 aldebaran systemd[1]: test@false.service: Service hold-off time over, scheduling restart.
Mär 08 00:44:21 aldebaran systemd[1]: test@false.service: Scheduled restart job, restart counter is at 3.
Mär 08 00:44:21 aldebaran systemd[1]: Stopped Testservice notification.
Mär 08 00:44:21 aldebaran systemd[1]: Started Testservice notification.
Mär 08 00:44:21 aldebaran systemd[1]: test@false.service: Main process exited, code=exited, status=1/FAILURE
Mär 08 00:44:21 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:44:21 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.
Mär 08 00:44:23 aldebaran systemd[1]: test@false.service: Service hold-off time over, scheduling restart.
Mär 08 00:44:23 aldebaran systemd[1]: test@false.service: Scheduled restart job, restart counter is at 4.
Mär 08 00:44:23 aldebaran systemd[1]: Stopped Testservice notification.
Mär 08 00:44:23 aldebaran systemd[1]: test@false.service: Start request repeated too quickly.
Mär 08 00:44:23 aldebaran systemd[1]: test@false.service: Failed with result 'exit-code'.
Mär 08 00:44:23 aldebaran systemd[1]: Failed to start Testservice notification.
Mär 08 00:44:23 aldebaran systemd[1]: test@false.service: Triggering OnFailure= dependencies.



Wie man sieht, sind immer 2 Sekunden Pause zwischen den einzelnen Aufrufen, bis dann in der vorletzten Zeile der Failed-Status eintritt, nachdem StartLimitBurst erreicht wird.

Das Verhalten entspricht in der Tat nicht der Manpage von systemd.

Und weil es mir nicht liegt, irgendwie auf irgendwen hinzupecken, nur weil es andere auch tun, hab ich genau dieses Verhalten auf der systemd-Mailingliste geschildert. Bin gespannt, was da zurück kommt.
Bisher hab ich auf dieser Liste immer nur positive Erfahrungen gemacht. Und ja, Pöttering diskutiert dort mit. Und man kann auch als keiner Debianforist mit The Master Himself diskutieren... das machen nicht nur irgendwelche Entwickler oder Journalisten...

lg scientific
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 08.03.2018 00:57:13

Was die Files in /tmp anbelangt: Ja, ich hoffe, das sonst kein Prozess diese aufgreift.
Das Problem ist, wenn ich sie in ein RuntimeDirectory lege, welches ich mit dem Aufruf der Unit erzeugen lasse, wird dieses Directory mit dem Stopp der Unit wieder entfernt. Ich kann doch nicht Aufrufübergreifend persistente Files ablegen.

Mit tmpfiles hab ich mich noch zu wenig beschäftigt, als dass ich die hier verwenden könnte.

lg scientific
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von NAB » 08.03.2018 05:02:56

scientific hat geschrieben: ↑ zum Beitrag ↑
08.03.2018 00:49:53
Bau dir einmal diese Test-Unit:
Ich hab damit schon im Sommer (?) rumgespielt, als ich auf Stretch und Systemd umgestiegen bin. Ich dachte mir nur "Oh, das ist aber komisch, vielleicht fixen sie das ja noch". Ich hab noch diese alte Spiel-Unit auf der Platte:

Code: Alles auswählen

[Unit]
Description=Lang laufender Dienst
StartLimitBurst=3
StartLimitIntervalSec=500
OnFailure=blabla.service

[Service]
#Type=oneshot
Type=simple
RemainAfterExit=no

ExecStart=/bin/sh -c "/bin/sleep 30; exit 1"
#ExecStart=/bin/sh -c "/bin/sleep 30"

Restart=on-failure
#Restart=on-success
RestartSec=10

[Install]
WantedBy=multi-user.target
Grad noch mal gestartet, zeigt immer noch das vom Manual abweichende Verhalten: OnFailure= wird vier mal ausgelöst, drei mal durch exit 1, ohne dass die Unit den "failed state" erreicht und das vierte mal nach/durch den "failed state". MMn reicht das so als "minimal example".

"systemctl status" zeigt dementsprechend in den drei mal 10 Sekunden RestartSec auch jeweils:
Active: activating (auto-restart) (Result: exit-code)
und nach dem vierten Versuch:
Active: failed (Result: exit-code)

Mir wird auch grad klar, was er im oben verlinkten Bugreport meinte. OnFailure reagiert nämlich auf zwei verschiedene Dinge. Einmal exit != 0 und einmal "Start request repeated too quickly". Diese unterschiedlichen Ereignisse möchte er wohl auseinanderhalten können.

Interessant auch dieses widersprüchliche Verhalten:
Das letzte Wort der Unit, so wie sie oben steht, ist:
Failed with result 'exit-code'.
Welcher exit-code? Die Unit wird gar nicht mehr gestartet, es gibt keinen exit-code.
Wenn ich umstelle auf:
Restart=on-success
und das exit 1 rausnehme, ist das letzte Wort der Unit:
Failed with result 'start-limit-hit'.
Joa, das macht mehr Sinn.
Der Status der Unit ist danach auch ein anderer (trotz gleicher "Beendigungs-Ursache"):
Active: failed (Result: start-limit-hit)
Uh?

Den Effekt kriegste völlig unabhängig von "OnFailure". Ich vermute, der ganze Code von Restart ist etwas "sloppy" und das Verhalten von OnFailure ist hier nur ein Symptom.

Wenn man OnFailure dann so benutzen möchte, wie es im Manual steht, nämlich als Reaktion auf die zugesichterte Eigenschaft "Der aufrufende Dienst ist garantiert mausetot", dann ist es kaputt, weil diese Eigenschaft eben nicht immer erfüllt ist. Manchmal ja, manchmal nein ...

Demenstsprechend wäre das, was hier im Thread vorgeschlagen wird, dann ein kreativer Bug Exploit von Systemd. Das finde ich zwar ausgesprochen lustig, aber ich glaube nicht, dass das etwas ist, was man Nastra empfehlen sollte.
scientific hat geschrieben: ↑ zum Beitrag ↑
08.03.2018 00:49:53
hab ich genau dieses Verhalten auf der systemd-Mailingliste geschildert.
:THX:
scientific hat geschrieben: ↑ zum Beitrag ↑
08.03.2018 00:57:13
Was die Files in /tmp anbelangt: Ja, ich hoffe, das sonst kein Prozess diese aufgreift.
Spricht was gegen /home/DEINLOGINUSER ?
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Nastra
Beiträge: 94
Registriert: 13.02.2018 05:12:27

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von Nastra » 08.03.2018 09:08:55

Guten Morgen,

uiii hier sind ja noch einige neue Erkenntnisse bezüglich einer systemd Lösung zu tage gekommen.

Da ich wie NAB schon gesagt hat eine zuverlässige Lösung suche, denke ich das ich von der systemd Lösung zur Überwachung der Instanzen vorerst Abstand nehme, da es scheinbar noch ziemlich verbugt ist.
Schade eigentlich da es auch ein ziemlich interessant Lösungsansatz ist wie @scientific ihn vorgeschlagen hat

@NAB habe das jetzt überall eingefügt und es läuft super :THX:


Gruß Nastra
Zuletzt geändert von Nastra am 08.03.2018 22:07:44, insgesamt 2-mal geändert.

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 08.03.2018 09:26:55

 @NAB hast du, außer zu spielen und dich damit über Pöttering zu ärgern, auch einen Bugreport verfasst?

Ich hab letzte Nacht an die Liste geschrieben und heute früh schon eine Antwort von Andrei Borzenkov bekommen:
This is apparently wrong, because service briefly goes via "failed"
state every time it fails. It is true that if Restart= is set it
immediately follows by "activating" state again, but OnFailure actions
are still taken.

So from end-user perspective unit indeed remains "failed" only when
limits are reached, but internally it does transition via "failed" state
every time.


>
> But in this testcase, the unit listet in OnFailure is called every time,
> the unit failes, restarts again fails again, and after 5 times
> (=StartLimitBurst), the unit falls into failed state... Here should be
> the only one time, where "OnFailure=" is hit...
>
> My systemd-Version is 237-3 from debian.
>
> Should i file a Bug in bugs.freedesktop.org?
>


You should create issue on github, this this where primary bug tracker
is today:

https://github.com/systemd/systemd/
Siehe da, er erkennt das Verhalten sofort als Bug an.

Ich werde den Bugreport verfassen und lasse euch wissen, ob und wie es gelöst wurde.

lg scientific
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 08.03.2018 10:05:01

Mein Bugreport im Bugtracker auf Github für systemd

https://github.com/systemd/systemd/issues/8398
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von NAB » 17.03.2018 03:22:05

Sorry für mein Schweigen hier, mich hatte die Grippe gründlich zerlegt. Eigentlich wollte ich noch was zu Systemd sagen. Die Lösung, ein Script über eine Service Unit zu starten ist zwar recht eingeschränkt, da man damit nur auf die Ereignisse "Dienst wird gestartet" und "Dienst wird beendet" reagieren kann, aber dafür kann man das wenigstens zielgenau tun und muss nicht "auf gut Glück" im Journal herumstochern.

Und eigentlich war mein toller Plan, dafür eine zusätzliche Überwachungs-Unit zu nehmen, die sich mit BindsTo= an den zu überwachenden Service hängt und bei jedem Start und Ende dieses Service eine Reaktion auslöst. Das hätte den Vorteil gehabt, dass man die vorhandenen Units nicht verändern muss. Leider scheitert die Idee am "Restart=". Für Type=oneshot verbietet mir Systemd die Benutzung von "Restart=" (gut, das macht Sinn) und für Type=simple wird "Restart=" einfach ignoriert (was am ExecStart=/bin/true liegen könnte). Ob das nun gewolltes Verhalten oder auch ein Bug ist, vermag ich der Gebrauchsanleitung nicht so recht zu entnehmen.

Somit sehe ich dann auch keine andere Möglichkeit, als hässlicher Weise in jede Unit, die man überwachen möchte, ein entsprechendes Script einzutragen:

Code: Alles auswählen

ExecStopPost=/bin/sh -c "/usr/bin/sudo -E -u pi /usr/local/bin/benachrichtigung.sh %n 1200"
Erläuterung: Das Script benachrichtigung.sh wird per sudo unter dem Benutzer "pi" gestartet, wann immer sich der ExecStart= Prozess dieser Unit beendet, egal aus welchem Grund. Das Script bekommt zwei Argumente: %n enthält den Namen der Service-Datei, die sich gerade beendet und die "1200" sind das von Nastra gewünschte Nachrichtenlimit in Sekunden. Das individuelle Nachrichtenlimit muss somit in jede zu überwachende Unit eingetragen werden.

Das Script benachrichtigung.sh sieht dann so aus:

Code: Alles auswählen

#!/bin/bash
# Erwartet, von Systemd aufgerufen zu werden, mit den
# Umgebungsvariablen $SERVICE_RESULT $EXIT_CODE und $EXIT_STATUS.
# siehe man systemd.exec
# Erwartet als ersten Parameter den Namen der aufrufenden .service Datei (%n).
# Erwartet als zweiten Parameter in Sekunden den minimalen Abstand zwischen zwei Nachrichten dieses Service.
# Erzeugt $arbeitsverzeichnis und speichert dort Zeitstempel. Räumt $arbeitsverzeichnis NICHT auf.

benutzer=pi
arbeitsverzeichnis=/home/$benutzer/dienstueberwachung

dienst=$1
abstand=$2

zeitstempel=$arbeitsverzeichnis/$dienst

# Debug:
# echo $(date) $dienst $abstand $SERVICE_RESULT $EXIT_CODE $EXIT_STATUS >> $arbeitsverzeichnis/debug.txt

if [ "$(whoami)" != "$benutzer" ]; then
   # echo "Falscher Benutzer $(whoami)" > $arbeitsverzeichnis/debug.txt
   exit 1
fi

mkdir -p $arbeitsverzeichnis
      
if [ -f "$zeitstempel" ]; then
    if [ $(($(cat "$zeitstempel") + $abstand)) -gt $(date +"%s") ]; then
      # echo "$(date) Zeitstempel zu neu" >> $arbeitsverzeichnis/debug.txt
      exit 0 # Keine Nachricht wenn Zeitstempel zu neu
   fi
fi

if [ "$SERVICE_RESULT" == "success" ]; then
   exit 0 # Keine Nachricht bei erfolgreicher Beendigung
fi

# Zeitstempel existiert nicht oder ist zu alt. Neuer Zeitstempel wird erzeugt:
echo $(date +"%s") > $zeitstempel

# Debug
# echo /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS" >> $arbeitsverzeichnis/debug.txt

/usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS"
Das Script ist möglichst einfach gehalten, mit dem Gedanken, dass man unerwünschte Teile leicht wieder rausreißen kann oder ihm weitere Tricks beibringen kann. Ich habe es grob mit exit 0, exit 1 und systemctl stop durchgetestet und bei mir funktioniert es erwartungsgemäß. Aber da ich weiterhin keine "homebridge" Dienste betreibe und kein ntfy installiert habe, mag ich für Nastras Verwendungszwecke keine Garantie übernehmen.

Ebenso könnte man mit ExecStartPre= noch auf das Ereignis "Dienst wird gestartet" reagieren, aber ich weiß nicht, ob das in diesem Kontext überhaupt sinnvoll ist.
scientific hat geschrieben: ↑ zum Beitrag ↑
08.03.2018 09:26:55
@NAB hast du, außer zu spielen und dich damit über Pöttering zu ärgern, auch einen Bugreport verfasst?
Nein, warum sollte ich? Ich halte den vorhandenen Bugreport für ausreichend. Ich sehe auch nicht dass (d)ein zweiter zu einer beschleunigten Bearbeitung führt.

Nebenbei, ich "ärgere" mich nicht über Poettering, ich amüsiere mich eher über ihn.
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 17.03.2018 22:24:08

Nun, wenn ein Bug zu ist, muss man einen neuen eröffnen, solange das Problem nicht gelöst ist.

Und wenn es genügend Leute bestätigen und dessen Behebung einfordern, wird sich was ändern.

Aber Pöttering belächeln und nix tun, ist halt auch feig und faul... So funktioniert Opensource halt nicht...
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von NAB » 18.03.2018 05:58:00

Ich glaub, mein Schwein pfeift ... warum zieht Systemd eigentlich immer die Vollspacken an?

Statt andere Leute als "feig und faul" zu beleidigen, lerne Lesen! Hier noch mal die beiden vorhandenen Bug-Reports:
https://bugs.freedesktop.org/show_bug.cgi?id=87799
https://github.com/systemd/systemd/issues/305
Versuche zu verstehen, wann die eröffnet wurden und wann sie aus welchem Grund geschlossen wurden. Wenn du dabei Hilfe brauchst, such dir welche, aber nicht in diesem Thread! Dann traut sich Nastra vielleicht doch noch mal her. Und wenn du deinen dämlichen Bug gefixt haben willst, dann schreibe einen Patch. Sonst interessiert sich einfach niemand dafür. So funktioniert Open Source.
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Nastra
Beiträge: 94
Registriert: 13.02.2018 05:12:27

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von Nastra » 18.03.2018 06:55:36

Guten Morgen zusammen,

@NAB ich hoffe es geht dir wieder besser, hatte schon vermutetet das du vielleicht im Urlaub bist :D
Habe deinen Beitrag gestern schon gelesen und natürlich auch kurz getestet, leider hat es nicht auf anhieb geklappt. Bin gestern leider auch nicht mehr dazu gekommen mich mit einem Feedback zu melden.

Erstmal vielen Dank für deine erneuten Mühen :THX:

Hier kurz erklärt wie ich vorgegangen bin:

Ich habe eine Unit von meinen Homebridge Instanzen gestoppt, geöffnet und die Zeile:

Code: Alles auswählen

ExecStopPost=/bin/sh -c "/usr/bin/sudo -E -u pi /usr/local/bin/benachrichtigung.sh %n 1200"
im Bereich [Service] eingetragen und einen deamon-reload durchgeführt. Die 1200 habe ich zum testen auf 30 gestellt.

Anschließend habe ich unter usr/local/bin das Skript mit dem Namen benachrichtigung.sh erstellt und die Rechte auf 755 gesetzt. Danach die config.json der Homebridge Instanz manipuliert das er mit status=1/FAILURE beendet.

Leider wurde ich nicht benachrichtig es scheint so als ob er noch ein Problem hat gem. Meldung unten?
Zusätzliche Info, das Arbeitsverzeichnis wurde angelegt und der ntfy Befehl im Skript funktioniert auch.

Code: Alles auswählen

Mär 17 07:21:24 HomeKitServer homebridge[954]: [2018-3-17 07:21:24] ---
Mär 17 07:21:24 HomeKitServer homebridge[954]: [2018-3-17 07:21:24] Loaded plugin: homebridge-mi-fan
Mär 17 07:21:24 HomeKitServer homebridge[954]: undefined:1
Mär 17 07:21:24 HomeKitServer homebridge[954]: x{
Mär 17 07:21:24 HomeKitServer homebridge[954]: ^
Mär 17 07:21:24 HomeKitServer homebridge[954]: SyntaxError: Unexpected token x in JSON at position 0
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at JSON.parse (<anonymous>)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at isConfig (/usr/lib/node_modules/homebridge-mi-fan/index.js:22:23)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Plugin.module.exports [as initializer] (/usr/lib/node_modules/homebridge-mi-fan/index.js:8:9)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Server.<anonymous> (/usr/lib/node_modules/homebridge/lib/server.js:160:14)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Array.forEach (<anonymous>)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Server._loadPlugins (/usr/lib/node_modules/homebridge/lib/server.js:138:22)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at new Server (/usr/lib/node_modules/homebridge/lib/server.js:56:24)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at module.exports (/usr/lib/node_modules/homebridge/lib/cli.js:26:16)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Object.<anonymous> (/usr/lib/node_modules/homebridge/bin/homebridge:17:22)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Module._compile (module.js:649:30)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Object.Module._extensions..js (module.js:660:10)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Module.load (module.js:561:32)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at tryModuleLoad (module.js:501:12)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Function.Module._load (module.js:493:3)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at Function.Module.runMain (module.js:690:10)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at startup (bootstrap_node.js:194:16)
Mär 17 07:21:24 HomeKitServer homebridge[954]:     at bootstrap_node.js:666:3
Mär 17 07:21:24 HomeKitServer systemd[1]: homebridge-test.service: Main process exited, code=exited, status=1/FAILURE
Mär 17 07:21:24 HomeKitServer sudo[1126]:     root : TTY=unknown ; PWD=/ ; USER=pi ; COMMAND=/usr/local/bin/benachrichtigung.sh homebridge-test.service 30
Mär 17 07:21:24 HomeKitServer sudo[1126]: pam_unix(sudo:session): session opened for user pi by (uid=0)
Mär 17 07:21:25 HomeKitServer sh[1125]: Traceback (most recent call last):
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/local/bin/ntfy", line 7, in <module>
Mär 17 07:21:25 HomeKitServer sh[1125]:     from ntfy.cli import main
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/local/lib/python2.7/dist-packages/ntfy/cli.py", line 12, in <module>
Mär 17 07:21:25 HomeKitServer sh[1125]:     from .data import scripts
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/local/lib/python2.7/dist-packages/ntfy/data.py", line 9, in <module>
Mär 17 07:21:25 HomeKitServer sh[1125]:     makedirs(ntfy_data_dir)
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/lib/python2.7/os.py", line 150, in makedirs
Mär 17 07:21:25 HomeKitServer sh[1125]:     makedirs(head, mode)
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/lib/python2.7/os.py", line 150, in makedirs
Mär 17 07:21:25 HomeKitServer sh[1125]:     makedirs(head, mode)
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/lib/python2.7/os.py", line 157, in makedirs
Mär 17 07:21:25 HomeKitServer sh[1125]:     mkdir(name, mode)
Mär 17 07:21:25 HomeKitServer sh[1125]: OSError: [Errno 13] Permission denied: '/root/.local'
Mär 17 07:21:25 HomeKitServer systemd[1]: homebridge-test.service: Control process exited, code=exited status=1
Mär 17 07:21:25 HomeKitServer systemd[1]: homebridge-test.service: Unit entered failed state.
Mär 17 07:21:25 HomeKitServer systemd[1]: homebridge-test.service: Failed with result 'exit-code'.
Mär 17 07:21:35 HomeKitServer systemd[1]: homebridge-test.service: Service hold-off time over, scheduling restart.
Mär 17 07:21:35 HomeKitServer systemd[1]: Stopped homebridge-test.service.
Mär 17 07:21:35 HomeKitServer systemd[1]: Started homebridge-test.service.
Gruß Nastra

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von NAB » 18.03.2018 16:21:55

Moin Nastra,

das sieht aber eigentlich ziemlich gut aus.
Nastra hat geschrieben: ↑ zum Beitrag ↑
18.03.2018 06:55:36

Code: Alles auswählen

Mär 17 07:21:24 HomeKitServer sudo[1126]:     root : TTY=unknown ; PWD=/ ; USER=pi ; COMMAND=/usr/local/bin/benachrichtigung.sh homebridge-test.service 30
Hier meldet sich sudo und möchte als Benutzer pi das Script /usr/local/bin/benachrichtigung.sh starten. Mit den beiden Argumenten "homebridge-test.service" und "30". Das erste ist die Unit, die sich gerade verabschiedet hat und das zweite ist das Nachrichtenlimit.

Als nächstes meldet sich dann ntfy:

Code: Alles auswählen

Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/local/bin/ntfy", line 7, in <module>
Mär 17 07:21:25 HomeKitServer sh[1125]:     from ntfy.cli import main
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/local/lib/python2.7/dist-packages/ntfy/cli.py", line 12, in <module>
Mär 17 07:21:25 HomeKitServer sh[1125]:     from .data import scripts
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/local/lib/python2.7/dist-packages/ntfy/data.py", line 9, in <module>
Mär 17 07:21:25 HomeKitServer sh[1125]:     makedirs(ntfy_data_dir)
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/lib/python2.7/os.py", line 150, in makedirs
Mär 17 07:21:25 HomeKitServer sh[1125]:     makedirs(head, mode)
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/lib/python2.7/os.py", line 150, in makedirs
Mär 17 07:21:25 HomeKitServer sh[1125]:     makedirs(head, mode)
Mär 17 07:21:25 HomeKitServer sh[1125]:   File "/usr/lib/python2.7/os.py", line 157, in makedirs
Mär 17 07:21:25 HomeKitServer sh[1125]:     mkdir(name, mode)
Mär 17 07:21:25 HomeKitServer sh[1125]: OSError: [Errno 13] Permission denied: '/root/.local'
Das sieht so aus als ob ntfy auf /root/.local zugreifen will. Und das darf es als Benutzer "pi" natürlich nicht. Kannst du dir darauf einen Reim machen? Das hat ntfy doch sonst nicht gemacht, oder? Hast du irgendwas an ntfy geändert? Oder an den Berechtigungen für /root/.local ?

Andererseits sagst du:
Nastra hat geschrieben: ↑ zum Beitrag ↑
18.03.2018 06:55:36
und der ntfy Befehl im Skript funktioniert auch.
Woran machst du das fest? Mir sieht es so aus als ob eben der ntfy Befehl das Problem macht.
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Nastra
Beiträge: 94
Registriert: 13.02.2018 05:12:27

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von Nastra » 18.03.2018 16:56:17

Code: Alles auswählen

Das sieht so aus als ob ntfy auf /root/.local zugreifen will. Und das darf es als Benutzer "pi" natürlich nicht. Kannst du dir darauf einen Reim machen? Das hat ntfy doch sonst nicht gemacht, oder? Hast du irgendwas an ntfy geändert? Oder an den Berechtigungen für /root/.local ?
Ne habe nichts geändert, alles wie gehabt.

Wenn ich die Zeile ins Terminal so eingebe, bekomme ich sofort eine Nachricht:

Code: Alles auswählen

pi@HomeKitServer:~ $ /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS"
Aber ich glaube ich habe den Fehler gerade gefunden, in dem Skript was ich zurzeit nutze wird der Befehl auch mit sudo und deinem -u pi versendet. Weiß zwar nicht wofür das -u pi steht, habe aber den Befehl jetzt mal abgeändert in:

Code: Alles auswählen

sudo -u pi /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS"
jetzt funktioniert er über das Terminal auch. Werde es gleich mal in Kombi mit dem Skript testen wenn ich daheim bin und mich wieder melden.

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 18.03.2018 17:05:01

Prinzipiell ist es in Skripten besser runuser statt su/sudo zu verwenden, wenn ein Skript als root läuft und unter einer anderen Benutzerkennung (in deinem Fall pi) ausgeführt werden soll.

su/sudo starten nämlich eine ganze pam-Session, was runuser nicht tut. Mit su im Skript kannst du dir seltsame Sideeffects holen, die runuser nicht verursacht.

Lg scientific
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von NAB » 18.03.2018 17:29:43

Ohhh ... ich ahne, was da schief läuft. Das "-E" im sudo-Aufruf sorgt dafür, dass alle Environment-Variablen übernommen werden, inklusive der von Systemd, die das Script braucht um herauszufinden, warum der Dienst sich beendet hat.

Ich befürchte, ntfy nutzt eine dieser von root stammenden Environment-Variablen und kommt dadurch auf die Idee, /root/.local benutzen zu wollen.

scientific, kann runuser da irgendwie helfen? So wie ich die man page verstehe, würde sich das gleiche Problem ergeben.

Nastra, ja, probier das mal aus. Ob es funktioniert hängt mMn davon ab, wie dein sudo konfiguriert ist. Das "-u pi" sorgt einfach nur dafür, dass der Befehl ntfy als Benutzer "pi" ausgeführt wird statt als "root".
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Nastra
Beiträge: 94
Registriert: 13.02.2018 05:12:27

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von Nastra » 18.03.2018 18:14:08

So, habe es jetzt getestet. Mit der Zeile funktioniert es und ich werde benachrichtigt. :THX: :THX: :THX:

Code: Alles auswählen

sudo -u pi /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS
Das ist die Meldung die mir in Telegram angezeigt wird, der exit-code 1 ist nur bei ausstieg mit FAILURE richtig? Ist es ggf. möglich das "FAILURE" mit in der Nachricht einzublenden?

Code: Alles auswählen

Dienst homebridge-hue.service ausgefallen mit exit-code 1

@NAB @scientific

Ist jetzt noch Handlungsbedarf bezüglich des runusers? Wenn ja was muss ich da genau machen?

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 18.03.2018 18:34:13

su durch runuser ersetzen. Sollte 1:1 funktionieren.

Ja, ich würds tun!

Runuser wird aus den Quellen von su gebaut und ist speziell für diese Zwecke.
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von NAB » 18.03.2018 20:33:32

Nastra, ich versuche dir mal zu erklären, welches Problem ich mit der Geschichte habe. Kurz zusammengefasst läuft es hinaus auf: es ist dein System.

Diese Zeile:

Code: Alles auswählen

ExecStopPost=/bin/sh -c "/usr/bin/sudo -E -u pi /usr/local/bin/benachrichtigung.sh %n 1200"
wird von deiner homebridge Unit aufgerufen, wann immer sie sich beendet. Die homebridge Unit läuft als root (deine Vorgabe, scheint so zu gehören). Das "sudo -E -u pi" wechselt dann sicherheitshalber die Benutzerrechte runter zum Benutzer "pi". Wo kommt der Benutzer pi her und was darf er? Keine Ahnung, wieder deine Vorgabe. Nun wird sudo hier als root ausgeführt, und da root bekanntlich alles darf, wird der Benutzerwechsel zu "pi" klappen, unabhängig von deiner sudo-Konfiguration. Das -E sorgt dafür, dass wir die "geheimen Botschaften" mitnehmen, in denen Systemd versteckt, warum deine homebridge sich beendet hat. Aus welchen Gründen kann so eine homebridge sich eigentlich beenden? Keine Ahnung, es ist dein Dienst.

Mit den Rechten von "pi" wird dann benachrichtigung.sh %n 1200 aufgerufen. Im %n versteckt sich der Dateiname der Systemd-Unit, die sich gerade beendet hat. Diesen Dateinamen missbrauche ich später, um den Zeitstempel darin zu speichern, im home-Verzeichnis von "pi". Bisher habe ich von dir nur "vernünftige" Dateinamen gesehen, aber was mag passieren, wenn du komische Sonderzeichen oder Leerzeichen einbaust? Keine Ahnung, das ist wieder dein Hoheitsgebiet.

Und nun zum Script benachrichtigung.sh. Wie gesagt läuft es unter den Benutzerrechten von "pi" - und geht mal dezent davon aus, dass "pi" ein Home-Verzeichnis hat. Da es komische Dateinamen auf deiner Platte speichert, die es nicht vollständig unter Kontrolle hat, fand ich es sicherer, die Benutzerrechte auf "pi" zu beschränken - so kann es im Problemfall weniger Schaden anrichten. Außerdem versucht es aus den "geheimen Botschaften" von Systemd schlau zu werden. Genauer gesagt aus den Variablen $SERVICE_RESULT $EXIT_CODE und $EXIT_STATUS.
So geheim sind die auch gar nicht, die sind hier dokumentiert:
https://www.freedesktop.org/software/sy ... .exec.html
ziemlich weit unten unter "Environment variables in spawned processes".
Wenn du genau hinguckst, ist die Sache etwas tricky. $SERVICE_RESULT kann zig verschiedene Werte annehmen:
"success", "protocol", "timeout", "exit-code", "signal", "core-dump", "watchdog", "start-limit-hit", "resources"
Beachte, dass "FAILURE" hier gar nicht auftaucht. Um es noch komplizierter zu machen, kann die Bedeutung von $EXIT_STATUS schwanken mit dem Inhalt von $SERVICE_RESULT. Wie wertet man das nun in deinem Interesse aus? Keine Ahnung. Das Script macht es sich momentan einfach: alles andere als "success" wird als Fehler behandelt und du wirst benachrichtigt. Ist das nun in deinem Interesse? Weiß ich nicht. Mit welchem $SERVICE_RESULT können sich deine Dienste überhaupt beenden? Keine Ahnung.

Ganz am Ende des Scriptes wird es dann spannend:

Code: Alles auswählen

/usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS"
Das funktioniert so nicht, da wir durch das -E die Umgebungsvariablen von root übernommen haben. ntfy kommt dadurch durcheinander und versucht auf Dateien von root zuzgreifen, obwohl es unter den Berechtigungen von "pi" läuft. Die korrekte Methode wäre jetzt herauszufinden, welche Umgebungsvariable das ist und diese auf den richtigen Wert zu setzen. Stattdessen kommst du mit einem Hack: du schreibst "sudo -u pi" davor. Das ist so einfach wie elegant - "pi" ruft hier sudo im eigenen Namen auf und da das -E hier fehlt, setzt sudo die Umgebungsvariablen auf die richtigen Werte für "pi". Schwupp, schon klappt es mit ntfy. Hier ruft also "pi" per sudo die Benutzerrechte von "pi" auf. Das ist von hinten durch die Brust ins Auge ... aber es funktioniert.

Das Problem an der Geschichte ist, dass es nur funktioniert, wenn sudo geeignet konfiguriert ist. "pi" muss berechtigt sein, per sudo in eigenem Namen ntfy aufzurufen. Klingt bescheuert, aber wenn das "pi" nicht ausdrücklich erlaubt ist, dann verhindert sudo die Ausführung von ntfy. Ist das nun gut so oder schlecht? Weiß ich nicht ... es ist ja dein System.

Wie du siehst ... es gibt eine ganze Menge Punkte, die eigentlich du entscheiden und abwägen musst. Insbesondere, bevor du die Lösung auf eine Horde unbedarfter Apple-User loslässt :wink:
Nastra hat geschrieben: ↑ zum Beitrag ↑
18.03.2018 18:14:08
der exit-code 1 ist nur bei ausstieg mit FAILURE richtig? Ist es ggf. möglich das "FAILURE" mit in der Nachricht einzublenden?
Wie oben erläutert, es gibt kein "FAILURE", darum kann man es auch nicht "einblenden". Du kannst aber einfach FAILURE in die Nachricht reinschreiben, wenn dir das so besser gefällt.
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 18.03.2018 21:07:39

Ich bleib dabei, auch wenn es mit OnFailure ein Problem von systemd gibt, mit meinen beiden einfachen Units hast du alles was du brauchst.

Wenn du mehr überwachen willst, würd ich ein Monitoring-System wie z. B. Zabbix installieren.
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 19.03.2018 09:34:22

Zabbix kannst du auch im Docker-Container installieren, ist FOSS, bietet eine feine Weboberfläche und die Möglichkeit über Trogger und Actions Emails und andere Benachrichtigungen zu versenden, wenn Services nicht laufen oder ausgefallen sind, die Load zu hoch ist, der Plattenplatz oder RAM knapp wird.

Wenn du deine Systeme beim Leben beobachten willst, ist das eine gute Wahl.

Lg scientific
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

Nastra
Beiträge: 94
Registriert: 13.02.2018 05:12:27

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von Nastra » 20.03.2018 04:41:56

Moin Moin,

@NAB Danke für die Ausführlich Antwort und Erklärung :THX:

Code: Alles auswählen

Das "sudo -E -u pi" wechselt dann sicherheitshalber die Benutzerrechte runter zum Benutzer "pi". Wo kommt der Benutzer pi her und was darf er? Keine Ahnung, wieder deine Vorgabe.
Der User pi ist der Standard User der durch die Raspberry Pi Foundation angelegt wird. Nutze diesen User so lange ich denen ihre Images nutze :roll:

Code: Alles auswählen

Aus welchen Gründen kann so eine homebridge sich eigentlich beenden?
Zum Beispiel wenn ein Gerät im Heimnetzwerk, ein Server von einem Hersteller der benötigt wird um mit der API zu kommunizieren nicht erreichbar ist oder das Homebridge Plugin schlecht programmiert ist. Fehler bleibt aber eigentlich immer FAILURE was es ja garnicht gibt..

Code: Alles auswählen

Bisher habe ich von dir nur "vernünftige" Dateinamen gesehen, aber was mag passieren, wenn du komische Sonderzeichen oder Leerzeichen einbaust? Keine Ahnung, das ist wieder dein Hoheitsgebiet.
Wird nicht vorkommen bei mir :mrgreen: Ne Spass, die Namenskonventionen habe ich bisher auch so in der kurz Anleitung zum erstellen von mehreren Instanzen bei uns im Forum festgelegt. Wenn einer Abweicht und ein Smilie einbaut ist es sein Problem :D

Code: Alles auswählen

und geht mal dezent davon aus, dass "pi" ein Home-Verzeichnis hat
Völlig richtig :THX:

Code: Alles auswählen

Das Script macht es sich momentan einfach: alles andere als "success" wird als Fehler behandelt und du wirst benachrichtigt. Ist das nun in deinem Interesse? 
Eigentlich schon, nur das normale Beenden durch den User soll es nicht berücksichtigen. Da es hier etwas nervig wäre. Kann man das irgendwie ausschließen?

Code: Alles auswählen

Mit welchem $SERVICE_RESULT können sich deine Dienste überhaupt beenden?
Bin ich ganz ehrlich, habe noch nie drauf geachtet für mich war bisher nur die selbständige Fehlerhaftebeendung interessant bei dem wir bisher von FAILURE gesprochen haben. Ich prüfe das mal.

Edit: Es gibt einmal diesen beim manuellen beenden:

Code: Alles auswählen

Mär 20 07:07:04 HomeBridgeServer homebridge[18513]: [2018-3-20 07:07:04] Got SIGTERM, shutting down Homebridge...
Mär 20 07:07:04 HomeBridgeServer systemd[1]: homebridge-test.service: Main process exited, code=exited, status=143/n/a
Mär 20 07:07:04 HomeBridgeServer sudo[18646]:     root : TTY=unknown ; PWD=/ ; USER=pi ; COMMAND=/usr/local/bin/benachrichtigung.sh homebridge-test.service 30
Mär 20 07:07:04 HomeBridgeServer sudo[18646]: pam_unix(sudo:session): session opened for user pi by (uid=0)
Mär 20 07:07:04 HomeBridgeServer sudo[18653]:       pi : TTY=unknown ; PWD=/ ; USER=pi ; COMMAND=/usr/local/bin/ntfy -b telegram send Dienst homebridge-test.service ausgefallen mit exit-code 143
Mär 20 07:07:04 HomeBridgeServer sudo[18653]: pam_unix(sudo:session): session opened for user pi by (uid=0)
Mär 20 07:07:05 HomeBridgeServer systemd[1]: Stopped homebridge-test.service.
Mär 20 07:07:05 HomeBridgeServer systemd[1]: homebridge-test.service: Unit entered failed state.
Mär 20 07:07:05 HomeBridgeServer systemd[1]: homebridge-test.service: Failed with result 'exit-code'.
und diesen wenn ein Fehler aufgetreten ist:

Code: Alles auswählen

Mär 20 07:02:31 HomeBridgeServer systemd[1]: homebridge-test.service: Main process exited, code=exited, status=1/FAILURE
Mär 20 07:02:31 HomeBridgeServer sudo[17051]:     root : TTY=unknown ; PWD=/ ; USER=pi ; COMMAND=/usr/local/bin/benachrichtigung.sh homebridge-test.service 30
Mär 20 07:02:31 HomeBridgeServer sudo[17051]: pam_unix(sudo:session): session opened for user pi by (uid=0)
Mär 20 07:02:31 HomeBridgeServer sudo[17058]:       pi : TTY=unknown ; PWD=/ ; USER=pi ; COMMAND=/usr/local/bin/ntfy -b telegram send Dienst homebridge-test.service ausgefallen mit exit-code 1
Mär 20 07:02:31 HomeBridgeServer sudo[17058]: pam_unix(sudo:session): session opened for user pi by (uid=0)
Mär 20 07:02:33 HomeBridgeServer systemd[1]: homebridge-test.service: Unit entered failed state.
Mär 20 07:02:33 HomeBridgeServer systemd[1]: homebridge-test.service: Failed with result 'exit-code'.

Code: Alles auswählen

as Problem an der Geschichte ist, dass es nur funktioniert, wenn sudo geeignet konfiguriert ist. "pi" muss berechtigt sein, per sudo in eigenem Namen ntfy aufzurufen. Klingt bescheuert, aber wenn das "pi" nicht ausdrücklich erlaubt ist, dann verhindert sudo die Ausführung von ntfy. Ist das nun gut so oder schlecht? Weiß ich nicht ... es ist ja dein System.
Mhhh, da muss ich leider auch passen so gut kenne ich mich mit den Benutzerrechten leider nicht aus. Aber so wie es jetzt ist wird es die Standardeinstellung sein die von der Pi Foundation vorgegeben ist und die bei 99% der Nutzer zutrifft vermute ich mal.

Code: Alles auswählen

Wie du siehst ... es gibt eine ganze Menge Punkte, die eigentlich du entscheiden und abwägen musst. Insbesondere, bevor du die Lösung auf eine Horde unbedarfter Apple-User loslässt  :wink: 
Deswegen bin ich ja hier um mir Fachkundigen Rat zu holen :mrgreen: :hail: :mrgreen:

Code: Alles auswählen

Wie oben erläutert, es gibt kein "FAILURE", darum kann man es auch nicht "einblenden". Du kannst aber einfach FAILURE in die Nachricht reinschreiben, wenn dir das so besser gefällt.
Da hätte man auch selber drauf kommen können :facepalm:

@scientific

Code: Alles auswählen

Wenn du mehr überwachen willst, würd ich ein Monitoring-System wie z. B. Zabbix installieren.
Habe ich mir gestern mal angeschaut, sieht sehr mächtig aus. Würde bestimmt seinen Zweck erfüllen, aber ich denke das es für den unbedarften Apple User wie NAB so schön sagt dann doch zu kompliziert wäre und für die reine Benachrichtigung über den Ausfall einer Intsatnz und ggf. eines Errors zu overloaded wäre :mrgreen:
Aber danke für den Tip!

Habe das mit dem runuser jetzt getestet, klappt leider nicht bekomme keine Ausgabe oder ich habe es falsch verstanden?

Code: Alles auswählen

runuser -u pi /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS"
und

Code: Alles auswählen

runuser /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS"

Danke euch beiden!

Lg Nastra

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 20.03.2018 09:18:06

Bei mir kommt in einr Rootshell ausgeführt

Code: Alles auswählen

 runuser -u scientific -- /usr/local/bin/ntfy -b telegram send 'Bla'
die Nachricht 'Bla' in Telegram an.

Trenne den Befehl, den du ausfühten willst, vom runuser mit '--' ab. Alles was nach -- kommt interpretiert runuser (wie su auch!) als den auszuführenden Befehl.

Willst du wirklich nur bei fehlerhaftem Ausfall von Homebridge benachrichtigt werden?

Und hast du noch immer deine 23 systemd-Units, oder hast du schon eine instanziierende, mit der du deine 23 Homebridge-Services aufrufst?

Lg scientific
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

breakthewall
Beiträge: 507
Registriert: 30.12.2016 23:48:51

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von breakthewall » 20.03.2018 10:24:41

NAB hat geschrieben: ↑ zum Beitrag ↑
18.03.2018 20:33:32
Diese Zeile:

Code: Alles auswählen

ExecStopPost=/bin/sh -c "/usr/bin/sudo -E -u pi /usr/local/bin/benachrichtigung.sh %n 1200"
wird von deiner homebridge Unit aufgerufen, wann immer sie sich beendet. Die homebridge Unit läuft als root (deine Vorgabe, scheint so zu gehören). Das "sudo -E -u pi" wechselt dann sicherheitshalber die Benutzerrechte runter zum Benutzer "pi".
Gerade wenn man bereits Systemd nutzt, und ein Systemd-Unit hat, dann kann man doch auch dynamische Nutzer generieren lassen. Alternativ kann man Systemdienste auch mittels Rootrechten starten, und hinterher die Rechte wieder automatisch gemäß "man systemd.exec" entziehen lassen. Zumal ein mittels Rootrechten gestarteter Prozess, die Privilegien eines Root nicht dauerhaft oder gar in vollem Umfang benötigt. Von daher ist das eine praktische Sache, die auch noch weitere Restriktionen ermöglicht.

Nastra
Beiträge: 94
Registriert: 13.02.2018 05:12:27

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von Nastra » 20.03.2018 11:22:05

@scientific

habe ich gemacht, hier das Ergebnis. Irgendwie hat er noch was zu meckern.

Code: Alles auswählen

pi@HomeBridgeServer:~ $ runuser -u pi -- /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS"
runuser: may not be used by non-root users

Code: Alles auswählen

Willst du wirklich nur bei fehlerhaftem Ausfall von Homebridge benachrichtigt werden?
Ich bin ganz ehrlich, ich bin zwischen allen Lösungen momentan hin und hergerissen. Habe ja alle ausprobiert.

Mit der Skript Variante reporter.sh bin ich bis jetzt am flexibelsten auch wenn es nicht die schönste Lösung ist wie wir ja schon festgestellt haben da das Journal die ganze Zeit beobachtet wird. Hier kann ich aber Loggen was ich möchte im Gegensatz zu allen Varianten die durch die Unit gesteuert werden.

Bei deiner systemd Lösung besteht ja scheinbar noch ein Bug, also läuft das vermutlich auch nicht 100 % rund soweit ich das aus dem Kontext herauslesen konnte. Daher habe ich das jetzt nicht weiterverfolgt. Bitte nicht böse sein.

Bei der Lösung von NAB systemd kombiniert mit dem letzten Skript funktioniert alles bis auf die kleinigkeit das er Benachrichtigt bei einem Ende durch den User. Denke mal das kann man auch noch ändern.

Ziel meines Anliegen war bei einem Fehler der Homebridge Instanz benachrichtig zu werden, ich glaube das Ziel haben wir schon mehrfach erreicht :THX:

Also zurück zu deiner Frage, ja klar möchte ich wenn möglich noch auf andere Ereignisse reagieren nach dem hier schon so viel erreicht wurde bin ja neugierig was geht oder was nicht aber es sollte auch nicht aus dem Ruder laufen was denn Schwierigkeitsgrad angeht.
Von allen Lösungen habe ich diese Funktion bisher nur bei der Möglichkeit mit dem reporter.sh und dem Loggen des Journal.

Code: Alles auswählen

Und hast du noch immer deine 23 systemd-Units, oder hast du schon eine instanziierende, mit der du deine 23 Homebridge-Services aufrufst?
Hatte ich komplett umgestellt auf einem Backup Image zum testen, auch hier bin ich ganz ehrlich ich konnte für meinen Zweck keinen riesen Vorteil finden da ich die Service Dateien in der Regel so gut wie nie anfasse. Die Befehle sind ja vom Grundsatz alle gleich geblieben statt einem - hatte ich dann ein @ beim starten und stoppen der Units.

Vielleicht habe ich ja auch den Vorteil noch nicht ganz Verstanden für meinen Anwendungsfall :roll: ?

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von scientific » 20.03.2018 12:47:50

Runuser führt man nur als root aus. Wenn dein Service als root läuft, verwende runuser statt sudo oder su um einen Befehl dann als anderer User (in deinem Fall pi) auszuführen.

Wenn du es testen willst, werde mit su oder sudo im Terminal zu root, und dann führe den runuser-Befehl wie oben aus.

Ich verstehe, dass du verwirrt bist... so viele schöne Lösungen... und eine Entscheidung ist immer ein Massenmord an Möglichkeiten... :wink:

Der Bug mit OnFailure ist zwar "lästig", wird aber mit der Konstruktion die ich dir vorgestellt habe, abgefangen. Das ist alles. Sollte das einmal behoben werden in systemd kann der Aufruf in der aufgerufenen Unit auch vereinfacht werden, da dann nur mehr einmal beim endgültigen Failure einer Unit eine Folgeunit gestartet wird... Für meinen Begriff kann man damit gut arbeiten. Vor allem wenn es darum geht, eine Benachrichtigung zu versenden, wenn ein Dienst fehlschlägt. Wie das geht, hab ich dir gezeigt. Zwei kleine Units und ein kurzes Shellskript. Kein ständiges Parsen des Journals usw...

Ich versteh auch nicht ganz, wozu du so "flexibel" sein musst um auf alles mögliche zu reagieren, wenn du eh nur eine Nachricht erhalten willst, wenn ein Homebridge-Service ausfällt...
Mit meiner Lösung kannst du dir von jedem einzelnen Dienst eine telegram-Nachricht schicken lassen, indem du ein Drop-In mit zwei Zeilen in /etc/systemd/system/ueberwachter.service.d/ ablegst... Mit deiner "flexiblen" Lösung musst du bei jeder neuen Unit dein Skript, die Parsoptionen fürs Journal usw. anpassen... Das musst du bei meiner Lösung nicht.

Der Vorteil an den instantiierenden Units liegt genau darin, dass du eine Änderung z.B. an der Abhängigkeit einer Überwachungs-Unit diese in einem einzigen File anpassen musst, und nicht in 23 verschiedenen. Das DropIn machst du ebenfalls nur für die instantiierende Unit und nicht für jede einzelne aufgerufene Instanz.

Wird der Service regulär beendet, kommt keine Nachricht. Das hast du ja manuell gemacht. Fällt der Service aus und kann nicht mehr restartet werden, kommt die Nachricht. Kommt der Service beim Booten nicht hoch, kommt die Nachricht. Zwei kleine Units... und du hast für jeden Service eine Überwachung parat.

lg scientific
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Gelöst! Shell Skript für systemd Überwachung

Beitrag von NAB » 20.03.2018 14:42:53

Nastra hat geschrieben: ↑ zum Beitrag ↑
20.03.2018 04:41:56
Edit: Es gibt einmal diesen beim manuellen beenden:

Code: Alles auswählen

Mär 20 07:07:04 HomeBridgeServer homebridge[18513]: [2018-3-20 07:07:04] Got SIGTERM, shutting down Homebridge...
Mär 20 07:07:04 HomeBridgeServer systemd[1]: homebridge-test.service: Main process exited, code=exited, status=143/n/a
Mär 20 07:07:04 HomeBridgeServer sudo[18646]:     root : TTY=unknown ; PWD=/ ; USER=pi ; COMMAND=/usr/local/bin/benachrichtigung.sh homebridge-test.service 30
Mär 20 07:07:04 HomeBridgeServer sudo[18646]: pam_unix(sudo:session): session opened for user pi by (uid=0)
Mär 20 07:07:04 HomeBridgeServer sudo[18653]:       pi : TTY=unknown ; PWD=/ ; USER=pi ; COMMAND=/usr/local/bin/ntfy -b telegram send Dienst homebridge-test.service ausgefallen mit exit-code 143
Mär 20 07:07:04 HomeBridgeServer sudo[18653]: pam_unix(sudo:session): session opened for user pi by (uid=0)
Mär 20 07:07:05 HomeBridgeServer systemd[1]: Stopped homebridge-test.service.
Mär 20 07:07:05 HomeBridgeServer systemd[1]: homebridge-test.service: Unit entered failed state.
Mär 20 07:07:05 HomeBridgeServer systemd[1]: homebridge-test.service: Failed with result 'exit-code'.
Aha? Das ist komisch. In meinen Primitiv-Tests hat er sich mit "success" beendet, wenn ich den Service mit systemctl stop beendet habe. Oder wie beendest du "manuell"?

Wie auch immer ... den Fall könnte man abfangen. Das Ende vom Script sähe dann so aus:

Code: Alles auswählen

if [ "$SERVICE_RESULT" == "success" ]; then
   exit 0 # Keine Nachricht bei erfolgreicher Beendigung
fi

if [ "$SERVICE_RESULT" == "exit-code" ] && [ "$EXIT_STATUS" == "143" ]; then
   exit 0 # Keine Nachricht bei SIGTERM
fi

# Zeitstempel existiert nicht oder ist zu alt. Neuer Zeitstempel wird erzeugt:
echo $(date +"%s") > $zeitstempel

# Debug
# echo /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS" >> $arbeitsverzeichnis/debug.txt

sudo -u pi /usr/local/bin/ntfy -b telegram send "Dienst $dienst ausgefallen mit $SERVICE_RESULT $EXIT_STATUS"
(Das sudo würde ich da ganz gerne auch wieder rauskriegen, aber im Moment ist es ganz praktisch, weil es dir im journal hinterlässt, was das Script so treibt. Darum kümmern wir uns später.)
breakthewall hat geschrieben: ↑ zum Beitrag ↑
20.03.2018 10:24:41
Gerade wenn man bereits Systemd nutzt, und ein Systemd-Unit hat, dann kann man doch auch dynamische Nutzer generieren lassen. Alternativ kann man Systemdienste auch mittels Rootrechten starten, und hinterher die Rechte wieder automatisch gemäß "man systemd.exec" entziehen lassen. Zumal ein mittels Rootrechten gestarteter Prozess, die Privilegien eines Root nicht dauerhaft oder gar in vollem Umfang benötigt. Von daher ist das eine praktische Sache, die auch noch weitere Restriktionen ermöglicht.
Stimmt. Aber ich schmiere hier in einer fremden Unit rum, die anscheinend als "root" laufen muss. Lediglich das ExecStopPost= soll als User "pi" laufen. Und ich möchte die fremde Unit so wenig wie möglich verunstalten.
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Antworten