Autostart von python script

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
franlog
User
Beiträge: 8
Registriert: Donnerstag 11. Januar 2018, 15:41

Hallo,

vorab: Python- und Raspberry Pi-technisch absoluter Neuling! :)

Ich hab ein Python Script geschrieben, welches auf dem Raspberry Pi läuft. Dieses Script lässt sich aus dem Terminal starten und funktioniert einwandfrei. Ich möchte das Script bei einem Reboot des Raspberry Pi gerne automatisch starten lasse. Jedoch weder ein cron job noch ein Eintrag in die rc.local starten das Script. Woran liegt das? Danke!

Code: Alles auswählen

# Tuerklingel
# Wenn es an der Tuer klingelt, wird von der nomosbox ein UDP Telegram an den RaspberryPI gesendet
# Der PI schreibt einen Eintrag in eine LOG Datei und loest ueber Asterisk einen Gruppenruf auf der Fritzbox aus

import time
import shutil
import os
import sys
import socket

# Einbinden der UDP sockets
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
# Festlegen der IP Adresse und des Ports auf dem gehoert werden soll (eigene IP)
sock.bind( ('XXX.XXX.XXX.XXX',54321) )


# .call Datei fuer Asterisk wird in den outgoing Ordner kopiert
def voip():		
        try:
            shutil.copyfile('/home/pi/flo/tuerklingel/tuerklingel.call','/var/spool/asterisk/outgoing/tuerklingel.call')
        except Exception:
            pass

			
# Log Eintrag wird geschrieben			
def log():
		file = open('/home/pi/flo/tuerklingel/tuerklingel.log',"a")
		file.write("%s: %s\n"  % (time.strftime("%d.%m.%Y %H:%M:%S"), "Es hat geklingelt"))
		file.close
		
		
# Empfang des UDP strings Klingel und Ausloesen der Aktionen	

while True:
    var1, addr = sock.recvfrom(1024)
    var2 = var1.decode('ascii')
#    print (var2)
    if var2 == "KLINGEL":
        voip()
        log()
#        print ("okay")

Eintrag in cronetab:
@reboot python /home/pi/flo/tuerklingel/tuerklingelscript.py

Wie gesagt:
Absoluter Newbie. Bitte nicht schlagen.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und wieder ein Opfer der vielen schlechten Rezepte im Internet, wie man autostart unter Linux implementiert. Kannst du nix fuer, aber es nervt die Betroffenen schon gehoerig.

crontab und rc.local sind sehr rudimentaere Moeglichkeiten etwas zu starten. Vor allem kennen sie keine Abhaengigkeiten von anderen Diensten oder Start-Vorgaengen.

Und das wird auch das sein, was dir hier das Genick bricht: dein Code setzt implizit vorraus, das das Netzwerk schon hochgefahren ist. Muss es aber nicht schon sein. Womit dein socket call fehlschlaegt.

Schreib stattdessen eine systemd-unit, in der du dein Skript startest, bei Absturz auch automatisch neu starten kannst, und welches von der Verfuegbarkeit des Netzwerks abhaengt. Dann ist das geloest. Dazu findet sich viel im Netz.

Und ein paar Anmerkungen zum Code:

- Dateien oeffnet man am besten mit dem with-statement:

Code: Alles auswählen

with open("dateiname", "modus") as f:
      # tuwas mit f
Dann werden die automatisch geschlossen, und bleiben nicht offen wie bei dir, denn dein "close" ohne Klammern ist eh wirkungslos.

- generell gibt es fuer logging das logging-Modul, und das kennt auch logging.exception(), womit du auch eventuelle Fehler loggen kannst, so das du erfaehrst, *warum* dein Programm nicht laueft.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@franlog: noch mehr Anmerkungen zum Code. Für bind benutzt man fast immer die Addresse '0.0.0.0' um auf alle Gateways zu lauschen. Eingerückt wird IMMER mit 4 Leerzeichen pro Ebene, nicht mal 8, 6, 4, ... . Funktionen sollte man auch Aufrufen `()`. var1 und var2 sind schlechte Variablennamen. Der Name sollte aussagekräftig sein.
franlog
User
Beiträge: 8
Registriert: Donnerstag 11. Januar 2018, 15:41

@Sirius3
Danke!
Variablennamen ist klar. Werden noch explizit vergeben.
Einrückung werde ich anpassen.
Das bind mache ich auf eine definierte Adresse, habe ich nur ausgeXt.
Wo rufe ich eine Funktion nicht auf?

@deets
Danke!
Werde mich an eine systemd-unit heranwagen!
franlog
User
Beiträge: 8
Registriert: Donnerstag 11. Januar 2018, 15:41

Habe jetzt einen Service angelegt. Aber auch über diesen startet das script nicht. Gibt es ein log, wo man Fehler auslesen kann?
  • [Unit]
    Description=tuerklingel
    After=network.target

    [Service]
    ExecStart=/usr/bin/python3 -u main.py
    WorkingDirectory=/home/pi/flo/tuerklingel/tuerklingelscript.py
    StandardOutput=inherit
    StandardError=inherit
    Restart=always
    User=pi

    [Install]
    WantedBy=multi-user.target
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich hab dir doch schon vom logging Modul erzählt. Damit kannst du sowhl dein normales logging machen, als auch eine mit try/except abfgefangene Exception.
franlog
User
Beiträge: 8
Registriert: Donnerstag 11. Januar 2018, 15:41

Kannst du damit was anfangen?
  • pi@FLO-RASPI3:~ $ sudo systemctl start tuerklingel.service
    pi@FLO-RASPI3:~ $ systemctl status tuerklingel.service
    ● tuerklingel.service - tuerklingel
    Loaded: loaded (/lib/systemd/system/tuerklingel.service; disabled; vendor preset: enabled)
    Active: failed (Result: exit-code) since Thu 2018-01-11 17:42:31 CET; 1s ago
    Process: 1349 ExecStart=/usr/bin/python3.5 -u main.py (code=exited, status=210/CHROOT)
    Main PID: 1349 (code=exited, status=210/CHROOT)

    Jan 11 17:42:31 FLO-RASPI3 systemd[1]: tuerklingel.service: Unit entered failed state.
    Jan 11 17:42:31 FLO-RASPI3 systemd[1]: tuerklingel.service: Failed with result 'exit-code'.
    Jan 11 17:42:31 FLO-RASPI3 systemd[1]: tuerklingel.service: Service hold-off time over, scheduling restart.
    Jan 11 17:42:31 FLO-RASPI3 systemd[1]: Stopped tuerklingel.
    Jan 11 17:42:31 FLO-RASPI3 systemd[1]: tuerklingel.service: Start request repeated too quickly.
    Jan 11 17:42:31 FLO-RASPI3 systemd[1]: Failed to start tuerklingel.
    Jan 11 17:42:31 FLO-RASPI3 systemd[1]: tuerklingel.service: Unit entered failed state.
    Jan 11 17:42:31 FLO-RASPI3 systemd[1]: tuerklingel.service: Failed with result 'exit-code'.
    pi@FLO-RASPI3:~ $
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein Working-Directory sollte auch ein Directory sein. Du gibst einen Datei an. Da wuerde ich mal anfangen.
franlog
User
Beiträge: 8
Registriert: Donnerstag 11. Januar 2018, 15:41

Hmm. Mist. Richtig.
Klappt aber immer noch nicht. Hier die aktueller Fehlerausgabe:
  • ● tuerklingel.service - tuerklingel
    Loaded: loaded (/lib/systemd/system/tuerklingel.service; disabled; vendor preset: enabled)
    Active: failed (Result: exit-code) since Thu 2018-01-11 18:09:58 CET; 5s ago
    Process: 1538 ExecStart=/home/pi/flo/tuerklingel/tuerklingelscript.py (code=exited, status=203/EXEC)
    Main PID: 1538 (code=exited, status=203/EXEC)

    Jan 11 18:09:58 FLO-RASPI3 systemd[1]: tuerklingel.service: Service hold-off time over, scheduling restart.
    Jan 11 18:09:58 FLO-RASPI3 systemd[1]: Stopped tuerklingel.
    Jan 11 18:09:58 FLO-RASPI3 systemd[1]: tuerklingel.service: Start request repeated too quickly.
    Jan 11 18:09:58 FLO-RASPI3 systemd[1]: Failed to start tuerklingel.
    Jan 11 18:09:58 FLO-RASPI3 systemd[1]: tuerklingel.service: Unit entered failed state.
    Jan 11 18:09:58 FLO-RASPI3 systemd[1]: tuerklingel.service: Failed with result 'exit-code'.
    pi@FLO-RASPI3:~ $
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist jetzt eher ein bug *im* script, und zum dritten mal: logging modul, exception rausschreiben.

https://stackoverflow.com/questions/519 ... -exception
franlog
User
Beiträge: 8
Registriert: Donnerstag 11. Januar 2018, 15:41

Okay, versuche mal das logging einzubinden. Auch wenn ich keinen Plan habe...
Warum funktioniert das script dann aber, wenn ich es im Terminal starte?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Weiss keiner, sonst braeuchte man kein logging.
franlog
User
Beiträge: 8
Registriert: Donnerstag 11. Januar 2018, 15:41

Magst du mir anhand meines scriptes im ersten post zeigen, wo und wie ich das logging einbauen muss?
Bekommst dann auch zu Weihnachten eine Karte von mir...
franlog
User
Beiträge: 8
Registriert: Donnerstag 11. Januar 2018, 15:41

Okay. Alle bugs gefunden. Auch ohne logging. :)
Hauptproblem war in dem service, dass ich das Python script mot Python und nicht mit Phyton3 aufgerufen habe.

Danke für den Tip, den Autostart als Service zu machen!
Antworten