Script überwachen und neu starten

  • Hallo,

    ich habe folgendes Problem. Mittels Python-Script steuer ich ein kleines PiOLED-Display (I²C) an einem Zero an, welches die Uhrzeit und diverse Werte ausgibt. Auf dem Zero läuft ein DHCP- und ein Webserver. Bildschirm o.ä. ist nicht angeschlossen, ich habe Zugang per SSH bzw. Webinterface. Der Pi läuft 24/7.

    Das funktioniert einwandfrei und auch im tagelangen Dauerbetrieb in einer Testumgebung perfekt. Das Script starte ich bei Raspi-Start über rc.local im Hintergrund ("&")

    Wenn das Gerät jedoch im echten Einsatz ist, dann kommt es vor, daß plötzlich das Display dunkel ist. Mittels "ps aux" kann ich dann sehen, daß das Script gar nicht mehr läuft. Es ist also irgendwann abgestürzt und beendet. In den Logfiles (/var/logs) finde ich nichts, was darauf schließen lassen könnte, andere Fehlermeldungen gibt es ja nicht.

    Bei der Suche konnte ich den Absturz darauf eingrenzen, daß das immer dann passiert, wenn die Prozessorlast durch Webanfragen plötzlich kurzzeitig extrem hoch ist. Das war in meiner Testumgebung nie der Fall, hab ich so nicht auf dem Schirm gehabt.

    Nun zur eigentlichen Frage? Wie kann ich es bewerkstelligen, daß das Script quasi auf Funktion überwacht wird und nach Absturz neu gestartet wird?

    Die PID zu überwachen ist IMHO nicht machbar, da das Script ja nach jedem Neustart des Gerätes eine andere hat. Man müßte also ersteinmal ermitteln, welche PID das Python-Script gerade hat. Ob das überhaupt geht, weiß ich nicht, übersteigt aber wohl auch meinen aktuellen Kenntnisstand.

    Mit einem Bash-Script a la

    Code
    while true
    do
      sudo python script.py &
      sleep 1
    done

    kann ich das zwar in einer Schleife laufen lassen, das ist aber völlig ungeeignet, weil ich dann ja jedesmal meine Displayanzeige neu starte, das wird auch nichts.

    Wie kann ich das lösen? Ich brauch praktisch einen Watchdog, der prüft, ob das Script noch läuft und wenn nicht, dieses neu startet.

  • Die rc.local ist veraltet und sollte man nicht mehr im Produktivsystem verwenden.

    Aktuell ist eine Systemd Service Unit. Eine kleine Anleitung findest Du hier: https://www.raspberrypi.com/documentation/…ating-a-service

    Das ist dem Beispiel enthaltene Restart=always sollte das Skript bei Absturz erneut starten.

    Und noch ein Link zur Übersicht von Restart=: https://www.freedesktop.org/software/syste…e.html#Restart=

  • Oh, danke, das klingt interessant.

    Dann läuft das Script praktisch als Systemdienst, wenn ich das richtig sehe. Und "Restart=always" startet automatisch neu, wenn es "abgewürgt" waurde?

    Muß in dem Fall auch das "&" mit gesetzt werden für Hintergrund und das sudo davor oder ist das als Systemdienst automatisch so.

  • Und "Restart=always" startet ...

    Genau.

    Muß in dem Fall auch das "&" mit gesetzt werden für Hintergrund

    Nein, das ist nicht nötig.

    und das sudo davor oder ist das als Systemdienst automatisch so.

    Das sudo kannst Du weglassen, aber dann musst Du in der Unit die Zeile User=pi weglassen, sonst wird Dein Skript als User pi gestartet.

  • So, es ist vollbracht und läuft erstmal. Ich werde berichten, ob es so klappt, wie erhofft und das Display erhellt bleibt.

    Der Start ist zumindest schonmal auch im syslog ordentlich gelistet. Da müßte ich dann ja Unregelmäßigkeiten sehen, so es welche gibt.

  • Systemd startet das Script, welches dann ein Python-Script in einer Endlosschleife aufruft.

    Das ginge einfacher, wenn du die Schleife in deinem Python-Script einbaust. Alternativ kannst du auch eine Timer-Unit verwenden. Wenn es darum geht Ressourcen zu sparen, dann sollte das Python-Script dauerhaft laufen. Ansonsten muss jedes mal der Interpreter erneut gestartet werden.

  • Hallo,

    es scheint zu funktionieren. 2 Dinge habe ich nach Auswertung der Logfiles noch geändert: ich hatte die Service-Datei mit Ausführungsrechten versehen, das hat syslog angemeckert, also CHMOD 644. Außerdem hat er den Pfad zum Pythoninterpreter "ExecStart=/usr/bin/python3" als "no such file or diectory" angemeckert.

    Es hat zwar einwandfrei funktioniert und stand auch so bei

    https://www.raspberrypi.com/documentation/…ating-a-service

    ist aber falsch, zumindest bei meiner Dateistruktur, wo der Pfad ein Syslink ist. Es darf aber KEIN Syslink sein, siehe https://raspberrypi.stackexchange.com/questions/1094…-on-systemstart

    Es muß ein absoluter Pfad sein. Da "python3" auf python3.xx, also eine Unterversion verlinkt und sich diese ja mit jedem Update ändern kann, habe ich einfach als Pfad "/usr/bin/python" genommen, da ja im Header des Scripts eh auf Python3 verwiesen wird.

    Jetzt sind die Fehler im Syslog verschwunden, es läuft einwandfrei.

    @DeaD_EyE,

    das war mein erster Gedanke, eine Schleife im Script. Aber die nutzt mir nichts, wenn das Script selbst abgewürgt wird. Bisher läuft die Variante als Systemdienst einwandfrei, um eine endgültige Aussage zu treffen, muß das aber noch ein paar Tage beobachtet werden.

  • Das ändert nichts an der Aussage selbst.

    Es ist nur aus einem anderen Blickwinkel: Ressourcen

    Am besten mal auf einer SD-Karte testen. Beim 2. Start wird er schneller sein, aufgrund des Caches. Der ist aber nicht unendlich und die Pfade müssen auch jedes Mal durchsucht werden und das nimmt auch Zeit in Anspruch.

    Code: Importzeit
    python3 -X importtime

    Es ist nur ein zusätzlicher Grund das zu vermeiden, was der OP aus einem anderen Grund vermeiden wollte.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!