ฉันจะอนุญาตให้แอป SDL (ไม่ทำงานในฐานะรูท) ใช้คอนโซลได้อย่างไร


14

ฉันต้องการใช้โปรแกรมที่ใช้ SDL เพื่อแสดงกราฟิกบนคอนโซลโดยไม่ต้องเข้าสู่ระบบจากคอนโซลและไม่เรียกใช้โปรแกรมเป็นรูท ตัวอย่างเช่นฉันต้องการที่จะสามารถเรียกใช้ผ่านทาง ssh ระบบปฏิบัติการเป้าหมายคือ raspbian

นี่เป็นตัวอย่างสั้น ๆ ใน python เพื่อแสดงปัญหา:

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

ใช้งานได้ (ทำงานจนเสร็จสมบูรณ์ไม่ส่งข้อยกเว้น) ถ้าฉันเรียกใช้จากคอนโซลและทำงานผ่าน ssh ถ้าฉันเรียกใช้เป็นรูต

ฉันตรวจสอบแล้วว่าผู้ใช้ของฉันอยู่ในกลุ่มเสียงและวิดีโอ

ฉันใช้ strace เพื่อดูความแตกต่างระหว่างการเรียกใช้จากคอนโซล (ซึ่งใช้งานได้) การใช้งานเป็น root ผ่าน ssh (ยังใช้งานได้) และใช้งานในฐานะผู้ใช้ทั่วไปผ่าน ssh (ไม่ทำงาน)

ข้อแตกต่างแรกคือผู้ใช้ของฉันไม่ได้รับอนุญาตให้เข้าถึง / dev / tty0 ฉันสร้างกลุ่มใหม่ (tty0) ใส่ผู้ใช้ของฉันในกลุ่มนั้นและเพิ่มกฎ udev เพื่อให้กลุ่มเข้าถึง / dev / tty0

เอาต์พุต strace เบี่ยงเบนไปจากการเรียกใช้ ioctl - ความล้มเหลวแสดงที่นี่; ioctl ส่งคืนค่า 0 เมื่อโปรแกรมรันจากคอนโซลหรือรันจาก ssh เป็น root:

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

(ที่อยู่ยังแตกต่างกัน แต่นั่นก็ไม่สำคัญ)

เนื่องจากโปรแกรมของฉันทำงานเมื่อทำงานเป็นรูทฉันคิดว่านี่หมายความว่าฉันมีปัญหาการอนุญาต ฉันจะให้สิทธิ์ที่จำเป็นแก่ผู้ใช้ของฉันเพื่อให้สามารถเรียกใช้โปรแกรมนี้ได้โดยไม่ต้องเข้าสู่ระบบที่คอนโซล (และไม่ต้องทำงานในฐานะรูท)


การเป็นเจ้าของ / การอนุญาตบนอุปกรณ์ framebuffer ของคุณคืออะไร?
Bandrami

นอกจากนี้โดยทั่วไปแล้ว / dev / tty ต้องการสมาชิกภาพในกลุ่มคอนโซลเพื่อเขียน
Bandrami

ajclarkson.co.uk/blog/pygame-no-rootดูเหมือนโซลูชัน
Arthur2e5

คำตอบ:


3

เป้าหมายของฉันเหมือนกับโปสเตอร์ต้นฉบับ แต่มีข้อแตกต่าง: ฉันต้องเรียกใช้แอปพลิเคชัน SDL เป็น systemd daemon เครื่อง Linux ของฉันคือ Raspberry Pi 3 และระบบปฏิบัติการคือ Raspbian Jessie ไม่มีแป้นพิมพ์หรือเมาส์เชื่อมต่อกับ RPi ฉันเชื่อมต่อด้วย SSH แอพ SDL ของฉันเป็นแอพPygameจริงๆ ฉันตั้งค่า pygame / SDL ให้ใช้ไดร์เวอร์ framebuffer“ fbcon” ผ่านตัวแปรสภาพแวดล้อม SDL_VIDEODRIVER systemd --versionผลลัพธ์ของฉันคือ:

systemd 215 + PAM + การตรวจสอบ + SELINUX + IMA + SYSVINIT + LIBCRYPTSETUP + GCRYPT + ACL + XZ -SECCOMP -APPARMOR

รุ่นแพ็คเกจ pygame ของฉันคือ: ( aptitude show python-pygame):

1.9.2 ~ ~ ก่อน r3348-2 ~ bpo8 + rpi1

เวอร์ชัน libSDL 1.2 ของฉันคือ: ( aptitude show libsdl1.2debian- ชื่อแพ็กเกจเครื่องของคุณอาจแตกต่างกัน):

1.2.15-10 + rpi1

สูตรอาหาร

  1. ตั้งค่าการอนุญาตสำหรับไฟล์ / dev / tty และ / dev / fb0 ดังที่อธิบายไว้ในคำตอบของ UDude ฉันค้นพบว่าการเปลี่ยนแปลงสิทธิ์ / dev / console ไม่จำเป็นใน Raspbian Jessie
  2. เพิ่มบรรทัดเหล่านี้ในส่วน [บริการ] ของไฟล์. service daemon ของคุณ:

    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
    

    ในกรณีที่ใครสนใจนี่คือไฟล์ pyscopefb.service ที่ฉันใช้:

    [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. ออกคำสั่งเหล่านี้ในพร้อมท์คำสั่ง (ฉันถือว่าไฟล์ pyscopefb.service ถูกวางไว้ในตำแหน่งที่ถูกต้องแล้วที่ systemd สามารถค้นหาได้):

    sudo systemctl daemon-reload
    sudo systemctl start pyscopefb
    

มันใช้งานได้สำหรับฉัน โปรดทราบว่าฉันไม่ได้ทดสอบว่าแอปพลิเคชัน pygame สามารถรับเหตุการณ์แป้นพิมพ์และเมาส์ได้หรือไม่

โบนัส

ฉันต้องแก้ไขอีก 2 ปัญหาซึ่งอาจเป็นที่สนใจเช่นกัน

  1. มีเคอร์เซอร์ข้อความกะพริบที่ด้านล่างของหน้าจอพร้อมกราฟิกเฟรมบุ๊กเกอร์ ในการแก้ไขปัญหานั้นฉันได้เพิ่มรหัสหลามต่อไปนี้ในแอปพลิเคชันซึ่งทำงานในแอพของฉันก่อนเริ่มต้น 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. หลังจากนั้นหน้าจอประมาณ 10 นาทีที่เชื่อมต่อกับเอาท์พุท HDMI ของ Raspberry Pi เปลี่ยนเป็นสีดำ (แต่ไม่ได้ปิด) และกราฟิกของฉันไม่แสดง แต่ Pygame รายงานว่าไม่มีข้อผิดพลาด สิ่งนี้กลายเป็นคุณสมบัติประหยัดพลังงาน หากต้องการปิดการใช้งานนั้นฉันได้เพิ่มรหัส Python ต่อไปนี้ซึ่งจะทำงานก่อนการเริ่มต้น 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
    

1
นี่เป็นประโยชน์อย่างมากสำหรับฉันในการเริ่มเล่นเกม pygame โดยไม่ต้องใช้แป้นพิมพ์เชื่อมต่อกับ Pi ของฉันดังนั้นขอบคุณ! ฉันต้องการพูดถึงว่าฉันพบว่ามันง่ายพอที่จะรัน pygame บน/dev/tty7และออกExecStartPre=/bin/chvt 7เพื่อหลีกเลี่ยงสิ่งเคอร์เซอร์และมีโบนัสไม่ชนกับ agetty ซึ่งทำงานโดยค่าเริ่มต้นใน tty1 – tty6
dctucker

2

แม้ว่าคำถามของคุณจะคลุมเครือเล็กน้อย (สิ่งที่มีความหมายโดยคอนโซล) ฉันจะพยายามตอบคำถามที่พบบ่อยที่สุด: / dev / console, / dev / tty, / dev / fb0 ... ปรับให้เข้ากับอุปกรณ์ที่คุณต้องการ เราถือว่าชื่อผู้ใช้คือ "myuser"

ดูการอนุญาตของอุปกรณ์ (นี่คือ 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

เริ่มปฏิบัติ

/ dev / คอนโซล

กลุ่มคือ "รูท" แต่ไม่อนุญาตการเข้าถึงกลุ่ม ฉันไม่ชอบเพียงแค่เพิ่มการอนุญาตให้กับกลุ่มรูทดังนั้นฉันจึงสร้างกลุ่มและ chgrp ไฟล์และเปลี่ยนการอนุญาต

$ 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> 

คุณสามารถใช้คำสั่งusermodเพื่อเพิ่มผู้ใช้ของคุณไปยังกลุ่มทั้งหมดข้างต้นได้เช่นกันหากคุณต้องการ


-1

จากประสบการณ์ล่าสุดของฉันนอกเหนือจากการให้สิทธิ์กับอุปกรณ์ tty ของคุณ (ดังที่ได้กล่าวไว้ก่อนหน้านี้) คุณต้องทำ 2 สิ่งเพิ่มเติม

  • การอนุญาตความสามารถ cap_sys_tty_config สำหรับความสามารถในการเรียกทำงาน หากคุณกำลังใช้โปรแกรมหลามคุณสามารถทำเช่นนั้นได้setcap cap_sys_tty_config+eip /usr/bin/python3.5(แทนพา ธ ของหลามด้วยของคุณ) แน่นอนว่าคุณต้องใช้ความสามารถนี้กับสคริปต์ไพ ธ อน
  • ใช้กระบวนการใน terminal เสมือนใหม่เช่นใช้ openvt: openvt ./your_script.py
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.