Python-pygame Skript läuft als Systemd-Service mit user 'pi'

  • Hallo,

    anläßlich der Diskussion über systemd:

    Mein Problem Python-Pygame-Skripte laufen nur mit root-Rechten.

    Starte ich ein Skript unter Benutzer 'pi', kommt die Fehlermeldung: "pygame.error: Unable to open a console terminal".

    Code
    ls -l /dev/console
    crw------- 1 root root 5, 1 Apr 27 21:24 /dev/console

    Es gibt ein Rezept, das Skript als Service mit Benutzer 'pi' zu starten.

    EDIT 04.05.2018 (Rechte) -->

    Benutzer 'pi muß in folgenden Gruppen sein

    Code
    pi@pipaos4:~/Peppy$ id
    uid=1001(pi) gid=1001(pi) groups=1001(pi),5(tty),27(sudo),29(audio),44(video),101(input)

    Rezept für den pygame-test service:

    <-- EDIT 04.05.2018 (Rechte)

    Das funktioniert auch.

    Da frage ich mich nach dem Unterschied.

    Auffällig sind mir die Parameter StandardInput, StandardOutput und TTYPath.

    Das man sagt dazu

    Spoiler anzeigen

    StandardInput=<br>

    • Controls where file descriptor 0 (STDIN) of the executed processes is connected to. Takes one of null, tty, tty-force, tty-fail, data, file:path, socket or fd:name.
    • If tty is selected, standard input is connected to a TTY (as configured by TTYPath=, see below) and the executed process becomes the controlling process of the terminal. If the terminal is already being controlled by another process, the executed process waits until the current controlling process releases the terminal.

    StandardOutput=

    • Controls where file descriptor 1 (STDOUT) of the executed processes is connected to. Takes one of inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+console, file: path, socket or fd:name.
    • tty connects standard output to a tty (as configured via TTYPath=, see below). If the TTY is used for output only, the executed process will not become the controlling process of the terminal, and will not fail or wait for other processes to release the terminal.

    TTYPath=

    • Sets the terminal device node to use if standard input, output, or error are connected to a TTY (see above). Defaults to /dev/console

    Meine Frage: kann ich die Service-Definition in ein Shell-Skript umwandeln?

    Schönen Gruß, kle

    EDIT:
    PS: probiert habe ich schon: python3 my-pygame-script.py </dev/tty2 >/dev/tty2

    gleicher Fehler: Unable to open a console terminal".

    In diesem Zusammenhang fiel mit noch auf "TTYPath= ...Defaults to /dev/console"

    EDIT 03.05.2018: Problem gelöst mit Manuls Beitrag #13 und #16

    4 Mal editiert, zuletzt von kle (4. Mai 2018 um 16:49) aus folgendem Grund: Problem gelöst. 04-05.2018 Rechte, wg. noisefloor Beitrag #7

  • Python-pygame Skript läuft als Systemd-Service mit user 'pi'? Schau mal ob du hier fündig wirst!

  • Ich schätze mal, der Unterschied liegt darin, daß die systemd unit mit root-Rechten startet und diese erst später fallen läßt. Vermutlich/möglicherweise hat sich systemd bis dahin bereits um die nötigen Berechtigungen gekümmrt.

    Ich sehe zwei Ansätze:

    • Bei laufender systemd unit nach deren geöffneten files schauen (lsof), das Terminal identifizieren, Berechtigungen überprüfen und schauen, ob diese gegenüber nicht laufender unit unterschiedlich sind.
    • Skript von Hand mit strace starten und schauen, an welcher Stelle es auf die Nase fällt. Berechtigungen der involvierten device überprüfen.

    Ich könnte mir vorstellen, daß es auf eine udev-Regel für die erforderlichen Berechtigungen hinausläuft.

  • Hallo Manul,

    das wußte ich schon:

    pygame.error: Unable to open a console terminal

    Dateinamen und Zeilennummer aus den tracebacks.

    Wenn mit der Meldung "/dev/console" gemeint ist, dafür gibts keine Rechte

    crw------- 1 root root 5, 1 May 1 19:26 /dev/console

    die taucht aber auch nicht mit lsof auf.

    mein user 'pi' ist in allen relevanten Gruppen (tty, video, inpiut):

    Code
    pi@pipaos4:~/Peppy$ id
    uid=1001(pi) gid=1001(pi) groups=1001(pi),5(tty),27(sudo),29(audio),44(video),101(input)

    folgende Geräte sind betroffen,

    1. wg. tty2 vor dem 1. service start:

    Code
    ls -l /dev/fb1 /dev/tty2 /dev/tty /dev/input/event0
    crw-rw---- 1 root video 29,  1 May  1 19:26 /dev/fb1
    crw-rw---- 1 root input 13, 64 May  1 19:26 /dev/input/event0
    crw-rw-rw- 1 root tty    5,  0 May  1 19:26 /dev/tty
    crw--w---- 1 root tty    4,  2 May  1 19:26 /dev/tty2

    2. wg. tty2 nach dem 1. service start:

    Code
    ls -l /dev/fb1 /dev/tty2 /dev/tty /dev/input/event0
    crw-rw---- 1 root video 29,  1 May  1 19:50 /dev/fb1
    crw-rw---- 1 root input 13, 64 May  1 19:26 /dev/input/event0
    crw-rw-rw- 1 root tty    5,  0 May  1 19:26 /dev/tty
    crw--w---- 1 pi   tty    4,  2 May  1 19:50 /dev/tty2

    auch nach service stop bleibt der /dev/tty2 owner 'pi'

    offene Dateien (/dev/console kommt nicht vor)

    ps Ausgabe

    Code
    ps -ef|egrep "1515|1522|1523|1524|1513|1520"
    pi        1513     1  0 19:50 tty2     00:00:00 /bin/bash /usr/local/bin/start-peppy-player.sh
    pi        1515  1513  2 19:50 tty2     00:00:51 python3 ./peppy.py
    pi        1520  1515  0 19:50 tty2     00:00:00 /bin/sh -c mplayer -ao alsa:device=hw -idle -slave -quiet -msglevel statusline=6 -msglevel global=6 -cache 8192 -cache-min 2 -volume 20
    pi        1521  1520  0 19:50 tty2     00:00:03 mplayer -ao alsa:device=hw -idle -slave -quiet -msglevel statusline=6 -msglevel global=6 -cache 8192 -cache-min 2 -volume 20

    das Ende der strace Ausgabe

    jetzt brauche ich weitere Ideen.

    Schönen Gruß, kle

  • Wenn mit der Meldung "/dev/console" gemeint ist

    Glaube ich eher nicht. Was wirklich gemeint ist, sollte der strace zeigen.

    auch nach service stop bleibt der /dev/tty2 owner 'pi'

    Hast Du mal ausprobiert, ob Du das Skript in diesem Zustand von Hand starten kannst? Bitte mit und ohne STDIN/OUT-redirection probieren!

    das Ende der strace Ausgabe

    Da hast Du zu viel weggekürzt, das ist nur noch das Ausgeben der Fehlermeldung, der eigentliche Fehler muß schon vorher aufgetreten sein.

  • Hallo Manul,

    Danke für die Unterstützung.

    Hier mein Verdacht:

    Da wird versucht /dev/tty zum Lesen und Schreiben zu öffnen ...

    und ioctl VT_GETSTATE geht schief.

    in diesem Zusammenhang fand ich, daß über ssh, der Framebuffer unter Umständen nicht erkannt wird.

    Ob das hier zutrifft weiß ich nicht. Ich arbeite aber über ssh.

    Die Textdatei (Attachmant unten) enthält die letzten 400 Zeilen von strace.

    Vorsichtshalber habe ich sie mit Windows-Zeilenende versehen.

    Den Obige Ausschnitt findest Du ab Zeile 277.

    Schönen Gruß, kle

  • Hast Du mal ausprobiert, ob Du das Skript in diesem Zustand von Hand starten kannst? Bitte mit und ohne STDIN/OUT-redirection probieren!

    Hallo Manul,

    das ist interessant:

    1.Service start und Stop

    Code
    pi@pipaos4:~/Peppy$ sudo systemctl start peppy-player
    pi@pipaos4:~/Peppy$ ls -l /dev/tty /dev/tty2
    crw-rw-rw- 1 root tty 5, 0 May  2 00:46 /dev/tty
    crw--w---- 1 pi   tty 4, 2 May  2 01:05 /dev/tty2
    pi@pipaos4:~/Peppy$ sudo systemctl stop peppy-player
    pi@pipaos4:~/Peppy$ ls -l /dev/tty /dev/tty2
    crw-rw-rw- 1 root tty 5, 0 May  2 00:46 /dev/tty
    crw--w---- 1 pi   tty 4, 2 May  2 01:05 /dev/tty2
    # jetzt ist pi owner von /dev/tty2, hat also Lese und Schreibrechte

    nach dem 1. Service Start und Stop

    Schönen Gruß, kle

  • Hallo,

    kle: dein 1. Post ist irrgeführend, weil das suggeriert wird, dass diese Service Unit die Lösung ist. Was du unterschlägst ist der 1. Teil der Antwort auf stackexchange.com, nämlich das Ändern der Rechte. Zitat von dort:

    "Set up permissions for /dev/tty and /dev/fb0 files as described in UDude’s answer. I discovered that /dev/console permission changes are not necessary in Raspbian Jessie."

    Das ist der Schritt, der erlaubt, dass `pi`die nötigen Rechte hat, um pygame-Skripte, die auf den Framebuffer zugreifen, zu starten.

    Gruß, noisefloor

  • Hallo,

    noisefloor permissions der devices und die groups von user 'pi' sind sichtbar in post #3

    Ausnahme: /dev/console das habe ich bisher ignoriert, weil im Trace das Gerät nicht vorkommt.

    wenn ich den Vorschlag von Dude mit der neuen group console versuche,

    sehe ich, daß die Rechte von /dev/console den Boot nicht überleben (Thema udev rules)

    Weiterhin, wenn ich (nach Dude's Änderung bezüglich /dev/console,)

    • mich in eine neue shell einlogge und
    • strace python <z.B. newtron-radio> starte,
    • kommt auch dann /dev/console nicht im Trace vor.

    Außerdem, Dude arbeitete mit jessie, ich mit pipaos-stretch und Peppy Player und python3.5.

    Ich habe das mal mit pipaos-guarana-console-5.0.img (das ist ein Jessie) und newtron-radio und python2.7 nachgetestet.

    Die Probleme scheinen mir identisch.

    Versuch doch mal ein strace in der systemd unit und vergleiche das mit dem vom händischen Aufruf. Eins von der Variante mit STDIN/OUT-Umleitung wäre evtl. auch noch interessant.

    das werde ich versuchen.

    1. ohne Redirection von StandardInput, StandardOutput im Service. Da erwarte ich Tracebacks

    2. mit Redirection, da sollte der Service mit systemctl stop peppy-player beendet werden.

    ich hoffe nur das filesystem läuft nicht über.

    Schönenb Gruß, kle

  • Hallo,

    ich habe die Stelle im Trace gefunden

    1. Service mit owner 'pi' und Redirection d.h. keine Tracebacks

    Code
      5954  open("/dev/tty0", O_WRONLY)             = 4
      5955  ioctl(4, VT_OPENQRY, 0x27482dc)         = 0
      5956  close(4)                                = 0
      5957  geteuid32()                             = 1001
      5958  open("/dev/tty", O_RDWR)                = 4
      5959  ioctl(4, VT_GETSTATE, 0x7e95ed60)       = 0
      5960  ioctl(4, KDGKBMODE, 0x7e95ed68)         = 0
      5961  ioctl(4, KDGKBENT, 0x7e95ed6c)          = 0
    ...

    2. direkt gestartet als user 'pi', also Tracebacks

    mit cd /home/pi/Peppy; strace python3 ./peppy.py > fehler.strace.txt 2>&1

    3. Service ohne Redirection, also Tracebacks

    aber anderes Fehlerbild

    Die Stelle wo es kracht, ist gefunden. Warum es aber kracht bleibt mir verborgen.

    nochmal, zwecks der Rechte

    Code
    pi@pipaos4:~/Peppy$ id
    uid=1001(pi) gid=1001(pi) groups=1001(pi),5(tty),27(sudo),29(audio),44(video),101(input)
    #
    pi@pipaos4:~/Peppy$ ls -l /dev/tty /dev/tty0 /dev/fb1 /dev/input/event0
    crw-rw---- 1 root video 29,  1 May  2 09:47 /dev/fb1
    crw-rw---- 1 root input 13, 64 May  2 09:47 /dev/input/event0
    crw-rw-rw- 1 root tty    5,  0 May  2 09:47 /dev/tty
    crw--w---- 1 root tty    4,  0 May  2 09:47 /dev/tty0

    Als mitglied der Gruppe tty darf ich eigentlich auf das Gerät /dev/tty lesen und schreiben.

    Warum kracht es trotzdem?

    Schönen Gruß, kle

  • Setz doch bitte mal beim Starten per systemd vor den eigentlichen Aufruf den Befehl tty und poste die Ausgabe.

    Außerdem könntest Du mal fuser -v /dev/tty* ausführen – einmal, während die unit läuft, und einmal, während sie nicht läuft.

  • Hallo Manul,

    dieses Skript wird im service aufgerufen

    Code
    pi@pipaos4:~/Peppy$ cat /usr/local/bin/start-peppy-player.sh
    #!/bin/bash
    #
    cd /home/pi/Peppy
    tty > ./ttt.tty.txt; python3 ./peppy.py

    tty liefert: /dev/tty2


    service peppy-player läuft

    Code
    pi@pipaos4:~$ fuser -v /dev/tty*
                         USER        PID ACCESS COMMAND
    /dev/tty:            pi         1470 F.... python3
    /dev/tty1:           pi          522 F.... bash
    /dev/tty2:           pi         1465 F.... start-peppy-pla
                         pi         1470 F.... python3

    service peppy-player läuft nicht

    Code
    pi@pipaos4:~$ fuser -v /dev/tty*
                         USER        PID ACCESS COMMAND
    /dev/tty1:           pi          522 F.... bash

    Schönen Gruß, kle

  • Hallo Manul,

    es geht,

    aber während tty2 dem user pi gehört

    zuerst ist das nicht der Fall:

    Code
    pi@pipaos4:~$ ls -l /dev/tty2
    crw--w---- 1 root tty 4, 2 May  2 21:59 /dev/tty2    # tty2 owned by root

    Dazu habe ich den service peppy-player gestartet und gestoppt.

    keine Tracebacks, der Peppy Player läuft so wie Du vorgeschlagen hast.

    Die Ursache ist vermutlich die Redirection im Service die auch nach service stop erhalten bleibt.

    Danach gehört tty2 dem user 'pi':

    Code
    pi@pipaos4:~/Peppy$ ls -l /dev/tty /dev/tty0 /dev/tty2 /dev/fb1 /dev/input/event0
    crw-rw---- 1 root video 29,  1 May  3 08:38 /dev/fb1
    crw-rw---- 1 root input 13, 64 May  2 21:59 /dev/input/event0
    crw-rw-rw- 1 root tty    5,  0 May  2 21:59 /dev/tty
    crw--w---- 1 root tty    4,  0 May  2 21:59 /dev/tty0
    crw--w---- 1 pi   tty    4,  2 May  3 08:29 /dev/tty2     # <-- tty2 owned by pi
    pi@pipaos4:~/Peppy$ id
    uid=1001(pi) gid=1001(pi) groups=1001(pi),5(tty),27(sudo),29(audio),44(video),101(input)

    openvt -c 2 -s -- python3 ./peppy.py

    Es funktioniert!

    Code
    pi@pipaos4:~/Peppy$ ps -ef|egrep "tty|python3"|grep -v grep
    root       439     1  0 08:24 tty1     00:00:00 /bin/login -f
    pi         523   439  0 08:24 tty1     00:00:00 -bash
    pi        1333     1  5 08:29 tty2     00:00:13 python3 ./peppy.py
    pi        1341  1333  0 08:29 tty2     00:00:00 /bin/sh -c mplayer -ao alsa:device=hw -idle  -slave -quiet -msglevel statusline=6 -msglevel global=6 -cache 8192 -cache-min  2 -volume 89
    pi        1367  1342  0 08:30 tty2     00:00:01 mplayer -ao alsa:device=hw -idle  -slave -quiet -msglevel statusline=6 -msglevel global=6 -cache 8192 -cache-min  2 -volume 89

    Vielen Dank Manul für Deine Hilfe.

    Jetzt fehlt mir nur noch eine elegante Möglichkeit das tty2 für pi zu reservieren.

    Schönen Gruß, kle

  • Hallo,

    Jetzt fehlt mir nur noch eine elegante Möglichkeit das tty2 für pi zu reservieren.

    Es geht z.B. als super user mit sudo chown pi /dev/tty2

    Welches verfügbare tty ich reserviere, ist egal, z.B. /dev/tty9.

    Auch openvt kann das 1. verfügbare Terminal ermitteln:

    openvt -s -- python3 ./peppy.py als user 'pi'.

    Wenn 'pi' noch nicht der owner bin kommt die Meldung:

    openvt: Unable to open /dev/tty2: Permission denied

    Danach könnte ich dieses reservieren mit:

    sudo chown pi /dev/tty2

    Danach sollte das openvt -s -- python3 ./peppy.py Kommando funktionieren.

    Schönen Gruß, kle

  • Hallo Manul,

    also Du überschreibst eine Default Regel für tty

    Code
    pi@pipaos4:/lib/udev/rules.d$ grep tty /lib/udev/rules.d/*rules
    ...
    50-udev-default.rules:SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620"
    ...

    Das ist eleganter.

    Schönen Gruß, kle

Jetzt mitmachen!

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