Bagaimana cara saya membiarkan aplikasi SDL (tidak berjalan sebagai root) menggunakan konsol

14

Saya ingin menggunakan program berbasis SDL untuk menampilkan grafik di konsol, tanpa harus masuk dari konsol, dan tanpa menjalankan program sebagai root. Sebagai contoh, saya ingin dapat menjalankannya melalui ssh. OS target adalah raspbian.

Berikut adalah contoh singkat dalam python untuk menggambarkan masalah:

import os, pygame
os.environ['SDL_VIDEODRIVER'] = 'fbcon'
pygame.init()
s = pygame.display.set_mode()
print "Success"

Ini berfungsi (berjalan sampai selesai, tidak membuang pengecualian) jika saya menjalankannya dari konsol, dan bekerja melalui ssh jika saya menjalankannya sebagai root.

Saya telah memeriksa bahwa pengguna saya ada di grup audio dan video.

Saya telah menggunakan strace untuk melihat apa yang berbeda antara menjalankannya dari konsol (yang berfungsi), menjalankannya sebagai root melalui ssh (juga berfungsi), dan menjalankannya sebagai pengguna biasa melalui ssh (tidak berfungsi).

Perbedaan pertama adalah bahwa pengguna saya tidak memiliki izin untuk mengakses / dev / tty0. Saya membuat grup baru (tty0), menempatkan pengguna saya di grup itu, dan menambahkan aturan udev untuk memberikan akses grup itu ke / dev / tty0.

Output strace menyimpang pada panggilan ioctl ini - kegagalan ditampilkan di sini; ioctl mengembalikan 0 ketika program dijalankan dari konsol atau dijalankan dari ssh sebagai root:

open("/dev/tty", O_RDWR)                = 4
ioctl(4, VT_GETSTATE, 0xbeaa01f8)       = -1 EINVAL (Invalid argument)

(Alamatnya juga berbeda, tapi itu tidak penting.)

Mengingat bahwa program saya berfungsi saat dijalankan sebagai root, saya pikir ini berarti saya memiliki masalah izin. Bagaimana cara memberikan izin yang diperlukan kepada pengguna saya untuk dapat menjalankan program ini tanpa masuk di konsol (dan tanpa menjalankan sebagai root)?

michael
sumber
Apa kepemilikan / izin pada perangkat framebuffer Anda?
Bandrami
Juga / dev / tty umumnya mengharuskan keanggotaan dalam grup konsol untuk menulis.
Bandrami
ajclarkson.co.uk/blog/pygame-no-root terlihat seperti solusi.
Arthur2e5

Jawaban:

3

Tujuan saya sama dengan poster asli, tetapi dengan satu perbedaan: saya perlu menjalankan aplikasi SDL sebagai daemon systemd. Mesin Linux saya adalah Raspberry Pi 3 dan sistem operasinya adalah Raspbian Jessie. Tidak ada keyboard atau mouse yang terhubung ke RPi. Saya terhubung dengannya menggunakan SSH. Aplikasi SDL saya sebenarnya adalah aplikasi berbasis Pygame . Saya mengatur pygame / SDL untuk menggunakan driver framebuffer “fbcon” melalui variabel lingkungan SDL_VIDEODRIVER. systemd --versionOutput saya adalah:

systemd 215 + PAM + AUDIT + SELINUX + IMA + SYSVINIT + LIBCRYPTSETUP + GCRYPT + ACL + XZ -SECCOMP -APPARMOR

Versi paket pygame saya adalah: ( aptitude show python-pygame):

1.9.2 ~ pre ~ r3348-2 ~ bpo8 + rpi1

Versi libSDL 1.2 saya adalah: ( aptitude show libsdl1.2debian- pada nama paket mesin Anda bisa berbeda):

1.2.15-10 + rpi1

Resep

  1. Siapkan izin untuk file / dev / tty dan / dev / fb0 seperti yang dijelaskan dalam jawaban UDude. Saya menemukan bahwa / dev / perubahan izin konsol tidak diperlukan di Raspbian Jessie.
  2. Tambahkan baris ini ke bagian [Layanan] pada file .service daemon Anda:

    User=pi #Your limited user name goes here
    StandardInput=tty
    StandardOutput=tty
    TTYPath=/dev/tty2   # I also tried /dev/tty1 and that didn't work for me
    

    Jika ada yang tertarik, berikut adalah file pyscopefb.service lengkap yang saya gunakan:

    [Unit]
    Description=Pyscopefb test service 
    Wants=network-online.target
    After=rsyslog.service
    After=network-online.target
    
    [Service]
    Restart=no
    ExecStart=/home/pi/Soft/Test/pygame/pyscopefb
    ExecStop=/bin/kill -INT $MAINPID
    OOMScoreAdjust=-100
    TimeoutStopSec=10s
    User=pi
    WorkingDirectory=/home/pi/Soft/Test/pygame
    StandardInput=tty
    StandardOutput=tty
    TTYPath=/dev/tty2
    
    [Install]
    WantedBy=multi-user.target
    
  3. Keluarkan perintah-perintah ini di command prompt (saya berasumsi file pyscopefb.service sudah ditempatkan ke lokasi yang benar di mana systemd dapat menemukannya):

    sudo systemctl daemon-reload
    sudo systemctl start pyscopefb
    

Ini bekerja untuk saya. Harap dicatat saya tidak menguji apakah aplikasi pygame dapat menerima acara keyboard dan mouse atau tidak.

Bonus

Saya juga harus menyelesaikan 2 masalah lain yang mungkin menarik juga

  1. Ada kursor teks berkedip di bagian bawah layar dengan grafis framebuffer. Untuk mengatasi itu, saya menambahkan kode Python berikut yang berjalan di aplikasi saya sebelum inisialisasi Pygame / SDL:

    def _disable_text_cursor_blinking(self):
        command_to_run = ["/usr/bin/sudo", "sh", "-c", "echo 0 > /sys/class/graphics/fbcon/cursor_blink"]
        try:
            output = subprocess32.check_output(command_to_run, universal_newlines = True)
            self._log.info("_disable_text_cursor_blinking succeeded! Output was:\n{output}", output = output)
        except subprocess32.CalledProcessError:
            self._log.failure("_disable_text_cursor_blinking failed!")
            raise
    
  2. Setelah sekitar 10 menit layar terhubung ke output HDMI Raspberry Pi menjadi hitam (tetapi tidak dimatikan) dan gambar saya tidak ditampilkan, meskipun Pygame melaporkan tidak ada kesalahan. Ini ternyata merupakan fitur hemat daya. Untuk menonaktifkannya, saya menambahkan kode Python berikut yang juga berjalan sebelum inisialisasi Pygame / SDL:

    def _disable_screen_blanking(self):
        command_to_run = ["/usr/bin/setterm", "--blank", "0"]
        try:
            output = subprocess32.check_output(command_to_run, universal_newlines = True)
            self._log.info("_disable_screen_blanking succeeded! Output was:\n{output}", output = output)
        except subprocess32.CalledProcessError:
            self._log.failure("_disable_screen_blanking failed!")
            raise
    
Roman Me
sumber
1
Ini sangat membantu saya untuk menyelesaikan memulai pygame tanpa memiliki keyboard yang terhubung ke Pi saya, jadi terima kasih! Saya ingin menyebutkan bahwa saya merasa cukup sederhana untuk menjalankan pygame /dev/tty7dan mengeluarkan sebuah ExecStartPre=/bin/chvt 7untuk menghindari hal kursor, dan itu memiliki bonus tidak bertabrakan dengan agetty yang berjalan secara default pada tty1-tty6.
dctucker
2

Meskipun pertanyaan Anda agak ambigu (apa yang dimaksud dengan konsol), saya akan mencoba menjawab untuk kasus yang paling umum: / dev / console, / dev / tty, / dev / fb0 ... sesuaikan ini ke perangkat yang Anda butuhkan. Kami menganggap nama pengguna adalah "pengguna saya".

Lihatlah izin perangkat (ini adalah ubuntu 15.04)

odroid@mbrxu3:~/projects/sc$ ls -l /dev/console
crw------- 1 root root 5, 1 Oct  23  17:49 /dev/console

odroid@mbrxu3:~/projects/sc$ ls -l /dev/tty
crw-rw-rw- 1 root tty 5, 0 Oct 24 17:50 /dev/tty

odroid@mbrxu3:~/projects/sc$ ls -l /dev/fb0 
crw-rw---- 1 root video 29, 0 Jan  1  2000 /dev/fb0

Mengambil tindakan

/ dev / console

grup adalah "root" tetapi tidak ada akses grup yang diizinkan. Saya tidak suka hanya menambahkan izin ke grup root, jadi alih-alih saya membuat grup dan chgrp file dan mengubah izin

$ sudo addgroup --system console
$ sudo chgrp console /dev/console
$ sudo chmod g+rw /dev/console
$ sudo usermod -a -G console <myuser>     <==== replace <myuser>

/ dev / tty

$ sudo usermod -a -G tty <myuser>

/ dev / fb0

$ sudo usermod -a -G video <myuser> 

Anda dapat menggunakan perintah usermod untuk menambahkan pengguna Anda ke semua grup di atas, jika itu adalah kebutuhan Anda.

UDude
sumber
-1

Dari pengalaman saya baru-baru ini, selain memberikan izin ke perangkat tty Anda (seperti yang disebutkan sebelumnya), Anda perlu melakukan 2 hal tambahan:

  • memberikan kap_sys_tty_config kapabilitas untuk dieksekusi. Jika Anda menggunakan program python, Anda dapat melakukannya seperti setcap cap_sys_tty_config+eip /usr/bin/python3.5(ganti jalur dengan python dengan Anda). Tentu saja, pertimbangkan bahwa Anda memberikan kemampuan ini untuk skrip python.
  • menjalankan proses di terminal virtual baru, misalnya menggunakan openvt: openvt ./your_script.py
Eriks Dobelis
sumber