查看设备的权限(这里是ubuntu 15.04)

查看设备的权限(这里是ubuntu 15.04)

我想使用基于 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 身份运行)的情况下运行该程序?

答案1

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

systemd 215 +PAM +AUDIT +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. 按照 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
    

答案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

采取行动

/开发/控制台

该组是“root”,但不允许任何组访问。我不喜欢只向根组添加权限,因此我创建一个组并 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> 

您可以使用用户模式如果您需要的话,也可以使用命令将您的用户添加到上述所有组中。

答案3

根据我最近的经验,除了向您的 tty 设备授予权限(如前所述)之外,您还需要做两件事:

  • 为可执行文件授予 cap_sys_tty_config 功能。如果您使用的是 python 程序,您可以这样做setcap cap_sys_tty_config+eip /usr/bin/python3.5(用您的路径替换 python 的路径)。当然,请考虑到您正在为任何 python 脚本授予此功能。
  • 在新的虚拟终端中运行该进程,例如使用 openvt:openvt ./your_script.py

相关内容