Chcę używać programu opartego na SDL do wyświetlania grafiki na konsoli, bez konieczności logowania się z konsoli i bez uruchamiania programu jako root. Na przykład chcę móc go uruchomić za pośrednictwem ssh. Docelowym systemem operacyjnym jest raspbian.
Oto krótki przykład w Pythonie, aby zilustrować problem:
import os, pygame
os.environ['SDL_VIDEODRIVER'] = 'fbcon'
pygame.init()
s = pygame.display.set_mode()
print "Success"
Działa to (działa do końca, nie zgłasza wyjątków), jeśli uruchomię go z konsoli i działa przez ssh, jeśli uruchomię go jako root.
Sprawdziłem, czy mój użytkownik jest w grupach audio i wideo.
Użyłem strace, aby zobaczyć, co różni się między uruchomieniem go z konsoli (co działa), uruchomieniem go jako root za pośrednictwem ssh (również działa) i uruchomieniem go jako zwykłego użytkownika za pomocą ssh (nie działa).
Pierwszą różnicą było to, że mój użytkownik nie miał uprawnień dostępu do / dev / tty0. Utworzyłem nową grupę (tty0), umieściłem mojego użytkownika w tej grupie i dodałem regułę udev, aby dać tej grupie dostęp do / dev / tty0.
Wyjście strace różni się przy tym wywołaniu ioctl - tutaj pokazana jest awaria; ioctl zwraca 0, gdy program jest uruchamiany z konsoli lub z ssh jako root:
open("/dev/tty", O_RDWR) = 4
ioctl(4, VT_GETSTATE, 0xbeaa01f8) = -1 EINVAL (Invalid argument)
(Adresy też się różnią, ale to nie jest ważne).
Biorąc pod uwagę, że mój program działa, gdy działa jako root, myślę, że to oznacza, że mam problem z uprawnieniami. Jak przyznać mojemu użytkownikowi niezbędne uprawnienia, aby móc uruchomić ten program bez logowania się na konsoli (i bez uruchamiania jako root)?
źródło
Odpowiedzi:
Mój cel był taki sam jak w przypadku oryginalnego plakatu, ale z jedną różnicą: musiałem uruchomić aplikację SDL jako demon systemd. Mój komputer z systemem Linux to Raspberry Pi 3, a system operacyjny to Raspbian Jessie. Do RPi nie jest podłączona klawiatura ani mysz. Łączę się z nim za pomocą SSH. Moja aplikacja SDL jest w rzeczywistości aplikacją opartą na Pygame . Ustawiam pygame / SDL, aby używało sterownika bufora ramki „fbcon” za pośrednictwem zmiennej środowiskowej SDL_VIDEODRIVER. Moje
systemd --version
wyniki to:Moja wersja pakietu pygame to: (
aptitude show python-pygame
):Moja wersja libSDL 1.2 to: (
aptitude show libsdl1.2debian
- na twoim komputerze nazwa pakietu może być inna):Przepis
Dodaj następujące wiersze do sekcji [Service] pliku .service demona:
Jeśli ktoś jest zainteresowany, oto kompletny plik pyscopefb.service, którego użyłem:
Wydaj te polecenia w wierszu polecenia (zakładam, że plik pyscopefb.service jest już umieszczony we właściwej lokalizacji, w której systemd może go znaleźć):
To działa dla mnie. Uwaga: nie testowałem, czy aplikacja pygame może odbierać zdarzenia z klawiatury i myszy, czy nie.
Premia
Musiałem też rozwiązać kolejne 2 problemy, które również mogą być interesujące
Na dole ekranu migał kursor tekstowy z grafiką bufora ramki. Aby rozwiązać ten problem, dodałem do mojej aplikacji następujący kod Python, który działa w mojej aplikacji przed inicjalizacją Pygame / SDL:
Po około 10 minutach ekran podłączony do wyjścia HDMI Raspberry Pi stał się czarny (ale nie wyłączony) i moja grafika nie wyświetlała się, chociaż Pygame nie zgłosiła błędów. Okazało się to funkcją oszczędzania energii. Aby to wyłączyć, dodałem następujący kod Python, który również działa przed inicjalizacją Pygame / SDL:
źródło
/dev/tty7
i wydaćExecStartPre=/bin/chvt 7
polecenie unikania kursora, i ma tę zaletę, że nie koliduje z agetty, które domyślnie działa na tty1 – tty6.Chociaż pytanie jest nieco dwuznaczne (co rozumie się przez konsolę), spróbuję odpowiedzieć na najczęstsze przypadki: / dev / console, / dev / tty, / dev / fb0 ... dostosuj to do potrzebnych urządzeń. Zakładamy, że nazwa użytkownika to „mój użytkownik”.
Spójrz na uprawnienia urządzenia (jest to Ubuntu 15.04)
Działaj
/ dev / console
grupa jest „root”, ale dostęp do grupy nie jest dozwolony. Nie lubię tylko dodawać uprawnień do grupy głównej, więc zamiast tego tworzę grupę, chgrp plik i zmieniam uprawnienia
/ dev / tty
/ dev / fb0
Możesz użyć polecenia usermod, aby dodać użytkownika również do wszystkich powyższych grup, jeśli tego potrzebujesz.
źródło
Z mojego niedawnego doświadczenia, oprócz udzielenia pozwolenia na twoje urządzenie tty (jak wspomniano wcześniej), musisz zrobić 2 dodatkowe rzeczy:
setcap cap_sys_tty_config+eip /usr/bin/python3.5
(zastąp ścieżkę python swoją). Oczywiście, weź pod uwagę, że przyznajesz tę możliwość dla dowolnego skryptu Pythona.openvt ./your_script.py
źródło