如何让SDL应用程序(不是以root用户身份运行)使用控制台


14

我想使用基于SDL的程序在控制台上显示图形,而不必从控制台登录,也不需要以root用户身份运行该程序。例如,我希望能够通过ssh运行它。目标操作系统是raspbian。

这是python中的一个简短示例来说明问题:

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

如果我从控制台运行它,则可以正常运行(运行到完成,不会引发异常),如果以root用户运行它,则可以通过ssh运行。

我检查了我的用户是否在音频和视频组中。

我已经使用strace来查看从控制台运行它(起作用),通过ssh以root身份运行(也可以工作)以及通过ssh以普通用户身份运行(不起作用)之间的区别。

第一个区别是我的用户没有访问/ dev / tty0的权限。我创建了一个新组(tty0),将用户置于该组中,并添加了udev规则以使该组可以访问/ dev / tty0。

strace输出在此ioctl调用处发散-此处显示失败;当程序从控制台运行或以root身份从ssh运行时,ioctl返回0:

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

(地址也有所不同,但这并不重要。)

鉴于我的程序在以root身份运行时可以运行,因此我认为这存在权限问题。如何为我的用户提供必要的权限,使其能够运行该程序而无需在控制台上登录(并且无需以root用户身份运行)?


帧缓冲设备的所有权/权限是什么?
邦德拉米

此外,/ dev / tty通常还需要控制台组中的成员身份才能写入。
邦德拉米

ajclarkson.co.uk/blog/pygame-no-root看起来像一个解决方案。
Arthur2e5

Answers:


3

我的目标与原始发布者的目标相同,但有一个区别:我需要将SDL应用程序作为systemd守护程序运行。我的Linux机器是Raspberry Pi 3,操作系统是Raspbian Jessie。RPi没有连接键盘或鼠标。我使用SSH连接到它。我的SDL应用程序实际上是基于Pygame的应用程序。我通过SDL_VIDEODRIVER环境变量将pygame / SDL设置为使用“ fbcon”帧缓冲驱动程序。我的systemd --version输出是:

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

我的pygame软件包版本为:(aptitude show python-pygame):

1.9.2〜pre〜r3348-2〜bpo8 + rpi1

我的libSDL 1.2版本是:(aptitude show libsdl1.2debian-您机器上的软件包名称可以不同):

1.2.15-10 + rpi1

食谱

  1. 如UDude的答案所述,为/ dev / tty和/ dev / fb0文件设置权限。我发现在Raspbian Jessie中不需要更改/ dev / console权限。
  2. 将这些行添加到守护程序的.service文件的[Service]部分:

    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应用程序是否能够接收键盘和鼠标事件。

奖金

我还必须解决另外两个可能也很有趣的问题

  1. 屏幕底部带有帧缓冲图形的文本光标闪烁。为了解决这个问题,我在应用程序中添加了以下Python代码,这些代码在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分钟后,连接到Raspberry Pi的HDMI屏幕变成黑色(但没有关闭电源),并且我的图形没有显示,尽管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
这对我在没有将键盘连接到我的Pi的情况下完成pygame的工作非常有帮助,所以谢谢!我想提一提,我发现运行pygame /dev/tty7并发出一个ExecStartPre=/bin/chvt 7避免光标的东西很简单,它的优点是不会与agetty冲突,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功能。如果您使用的是python程序,则可以这样做setcap cap_sys_tty_config+eip /usr/bin/python3.5(用您的python路径替换)。当然,要考虑到您正在为任何python脚本授予此功能。
  • 在新的虚拟终端中运行该进程,例如使用openvt: openvt ./your_script.py
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.