2016-08-29 6 views
3

Ich versuche, ein Python-Pygame-Skript mit Systemd auszuführen, und aus irgendeinem Grund wird das Skript einfach ohne einen Fehler beendet. Dies ist auf einem Raspberry Pi mit Raspian "Jessie Lite".pygame.init() schlägt fehl, wenn mit systemd ausgeführt

Wenn ich das Skript manuell mit "sudo python myscript.py" ausführen, funktioniert es gut.

sudo systemctl Status myscript.service Berichte:

* myscript.service - Python Script 
Loaded: loaded /etc/systemd/system/myscript.service; enabled) Active: inactive (dead) since Mon 2016-08-29 04:33:19 UTC; 1s ago 
Process: 3275> ExecStart=/usr/bin/python /home/pi/myscript.py (code=killed, signal=HUP) 
Main PID: 3275 (code=killed, signal=HUP) 

Wenn ich den Dienst manuell mit sudo starten systemctl starten myscript.service das gleiche passiert.

Ich habe mein Skript auf den Aufruf pygame.init() reduziert. Hier endet es.

Wenn ich versuche, die Module manuell zu initialisieren, werden "cdrom", "Joystick", "threads" und "font" normal initialisiert, aber ein Aufruf von display.init() bewirkt, dass das Programm beendet wird. Es gibt keine Ausnahme.

Die einzige Ressource, die ich online finden konnte, ist this guy. Es scheint, als wäre er genau auf dasselbe gestoßen, was ich sehe. Ich habe strace versucht und wenn ich lange genug warte (2 Minuten), wird es funktionieren! Offensichtlich kann ich die ganze Zeit nicht mit strace rennen. Ich denke, es verlangsamt die Ausführung der Initialisierung, damit es irgendwie funktioniert.

EDIT: Das Problem scheint systemd Senden einer SIGHUP. Wenn dies in Python nicht behandelt wird, wird standardmäßig die Aktion beendet. Eine schnelle Lösung ist der Haken SIGHUP:

import signal 
def handler(signum, frame): 
    pass 

try: 
    signal.signal(signal.SIGHUP, handler) 
except AttributeError: 
    # Windows compatibility 
    pass 

So viele brennende Fragen. Warum macht Systemd das? Warum repariert Strace das Problem? Warum erhalten einige Python-Skripte SIGHUP, während andere dies nicht tun?

+0

Klingt wie ein Fehler oder Konfigurationsproblem. Systemd sollte 'SIGHUP' nicht senden, außer über' SendSIGHUP = 'oder' KillSignal = '... – dhke

Antwort

0

Überprüfen Sie zuerst Ihre Protokolle:

journalctl -u myservice.service 

diese zu Ihrem Gerät Datei hinzufügen kann die Protokollierung verbessern:

StandardOutput=journal+console 

In einigen Fällen, wenn einige Protokollierung kurz vor den Service-Exits geschieht, die Protokolle wird nicht mit dem Service getaggt, also nachdem Sie den Dienst ausgeführt haben, schauen Sie sich auch an:

Für Einträge unmittelbar nach dem Verlassen des Dienstes.

Versuchen Sie statt dessen auch network.target mit der network-online.target.

Ich nehme an, dass die App von der Befehlszeile selbst ausgeführt wird. Vorausgesetzt, es funktioniert so und nicht von systemd, können unterschiedliche Umgebungsvariablen ein Problem sein. Fügen Sie am Anfang Ihrer App eine Zeile hinzu, um alle Umgebungsvariablen auszugeben, und vergleichen Sie diese Ausgabe, wenn sie von systemd über die CLI ausgeführt wird.

Überprüfen Sie abschließend die Dokumentation für Type=. Wenn der Standardtyp = nicht auf Ihren Fall zutrifft, legen Sie dies entsprechend fest.

Zukünftige spezifische Fragen zu systemd können besser bei Unix & Linux StackExchange beantwortet werden, da sie sich nicht direkt auf die Programmierung beziehen.

Sie sollten auch Ihre systemd Unit-Datei posten, da Sie damit Probleme haben.

+0

Mein Python-Skript schreibt sein eigenes Logfile, also weiß ich, dass es ausgeführt wird und wie weit es kommt. Ich glaube nicht, dass es sich um ein Systemkonfigurationsproblem handelt. Gute Idee über die Umgebungsvariablen. Ich habe die Umgebung in Systemd mit den Tags "Environment =" abgeglichen, so dass es genau so aussieht wie bei der Ausführung in der Befehlszeile, aber es hat nicht geholfen. – user5541269

0

Ich habe keine Antwort, aber ich habe die gleiche Sache, also werde ich ein paar mehr Details hinzufügen.

Hier ist der Cut-down-Code:

#!/usr/bin/python2.7 

import logging 
from pygame import display 
import signal 
import time 

def handler(signum, frame): 
    """Why is systemd sending sighups? I DON'T KNOW.""" 
    logging.warning("Got a {} signal. Doing nothing".format(signum)) 

signal.signal(signal.SIGHUP, handler) 
signal.signal(signal.SIGTERM, handler) 
signal.signal(signal.SIGCONT, handler) 

logging.warning("About to start display.") 
try: 
    display.init() # hups 
except Exception as ex: 
    logging.warning("Got any exception: %s " % ex) 

logging.warning("Quitting in 60") 
time.sleep(60) 

Hier ist das Protokoll, das produziert:

Jul 8 22:30:27 beardog systemd[1]: Started PyGame Test. 
Jul 8 22:30:27 beardog pygame[17406]: WARNING:root:About to start display. 
Jul 8 22:30:27 beardog pygame[17406]: WARNING:root:Got a 1 signal. Doing nothing 
Jul 8 22:30:27 beardog pygame[17406]: WARNING:root:Got a 18 signal. Doing nothing 
Jul 8 22:30:27 beardog pygame[17406]: WARNING:root:Quitting in 60 

Es ist eine SIGCONT unmittelbar nach dem SIGHUP bekommen, aber keine SIGTERM. System behauptet, immer nur einen SIGHUP nach einem SIGTERM zu senden, also kommt es vielleicht von woanders her? Ich kann jedoch nichts im Pygame-Code finden.

Ich habe Systemd Debug Logging eingeschaltet, aber es wird nichts Interessantes gedruckt.

Hier ist meine Systemkonfiguration.

Ich habe dies als Typ = forking, oneshot und dbus versucht (obwohl es keine von ihnen ist). Ich habe auch TimeoutStartSec = 20 versucht, aber keine Änderung. Getestet auf einem Ubuntu Xenial Laptop und auf einem Raspberry Pi mit Raspbian. Sowohl python2.7 als auch python3. Code funktioniert gut, wenn er manuell ausgeführt wird, und scheint zu funktionieren, wenn er unter strace in systemd ausgeführt wird./o \

Wie das OP kann ich umgehen, indem ich die SIGHUP, aber nach dieser viel Debugging ich würde gerne wissen, was los ist.

Verwandte Themen