콘솔에 로그인하거나 프로그램을 루트로 실행하지 않고 SDL 기반 프로그램을 사용하여 콘솔에 그래픽을 표시하고 싶습니다. 예를 들어 SSH를 통해 실행할 수 있기를 원합니다. 대상 운영체제는 Raspbian입니다.
다음은 문제를 설명하기 위해 Python으로 작성된 간단한 예입니다.
import os, pygame
os.environ['SDL_VIDEODRIVER'] = 'fbcon'
pygame.init()
s = pygame.display.set_mode()
print "Success"
콘솔에서 실행하면 작동하고(예외가 발생하지 않고 완료될 때까지 실행), 루트로 실행하면 ssh를 통해 작동합니다.
내 사용자가 오디오 및 비디오 그룹에 있는지 확인했습니다.
strace를 사용하여 콘솔에서 실행(작동), ssh를 통해 루트로 실행(역시 작동), 일반 사용자로 ssh를 통해 실행(작동하지 않음) 사이의 차이점을 확인했습니다.
첫 번째 차이점은 내 사용자가 /dev/tty0에 액세스할 수 없다는 것입니다. 새 그룹(tty0)을 만들고 내 사용자를 해당 그룹에 넣은 다음 그룹에 /dev/tty0에 대한 액세스 권한을 부여하는 udev 규칙을 추가했습니다.
strace 출력은 이 ioctl 호출에서 분기됩니다. 여기에는 프로그램이 콘솔이나 ssh에서 루트로 실행될 때 ioctl이 0을 반환합니다.
open("/dev/tty", O_RDWR) = 4
ioctl(4, VT_GETSTATE, 0xbeaa01f8) = -1 EINVAL (Invalid argument)
(주소도 다르지만 상관없습니다.)
내 프로그램이 루트로 실행될 때 제대로 작동한다는 점을 감안할 때 이는 권한 문제가 있음을 의미한다고 가정합니다. 콘솔에 로그인하지 않고(그리고 루트로 실행하지 않고) 이 프로그램을 실행할 수 있도록 사용자에게 필요한 권한을 부여하려면 어떻게 해야 합니까?
답변1
내 목표는 원본 포스터의 목표와 동일하지만 한 가지 차이점이 있습니다. SDL 애플리케이션을 systemd 데몬으로 실행해야 한다는 것입니다. 내 Linux 컴퓨터는 Raspberry Pi 3이고 운영 체제는 Raspbian Jessie입니다. RPi에 연결된 키보드나 마우스가 없습니다. SSH를 사용하여 연결합니다. 내 SDL 애플리케이션은 실제로파이게임애플리케이션 기반. SDL_VIDEODRIVER 환경 변수를 통해 "fbcon" 프레임 버퍼 드라이버를 사용하도록 pygame/SDL을 설정했습니다. 내 systemd --version
결과는 다음과 같습니다
systemd 215 +PAM +AUDIT +SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ -SECCOMP -APPARMOR
내 파이게임 패키지 버전은: ( aptitude show python-pygame
):
1.9.2~이전~r3348-2~bpo8+rpi1
내 libSDL 1.2 버전은 다음과 같습니다. ( aptitude show libsdl1.2debian
- 패키지 이름은 컴퓨터에 따라 다를 수 있습니다.)
1.2.15-10+rpi1
레시피
- UDude의 답변에 설명된 대로 /dev/tty 및 /dev/fb0 파일에 대한 권한을 설정하십시오. Raspbian Jessie에서는 /dev/console 권한을 변경할 필요가 없다는 것을 알았습니다.
데몬 .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
명령 프롬프트에서 다음 명령을 실행합니다(pyscopefb.service 파일이 systemd가 찾을 수 있는 올바른 위치에 있다고 가정합니다).
sudo systemctl daemon-reload sudo systemctl start pyscopefb
이것은 나에게 효과적입니다. 파이게임 응용프로그램이 키보드와 마우스 이벤트를 수신할 수 있는지 여부는 테스트하지 않았다는 점에 유의하십시오.
보너스
또한 흥미로울 수 있는 다른 두 가지 문제도 해결해야 합니다.
프레임 버퍼 그래픽과 함께 화면 하단에 깜박이는 텍스트 커서가 있습니다. 이 문제를 해결하기 위해 Pygame/SDL이 초기화되기 전에 내 애플리케이션에서 실행되는 다음 Python 코드를 추가했습니다.
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
약 10분 후에 Raspberry Pi의 HDMI 출력에 연결된 화면이 검게 변하고(그러나 꺼지지는 않음) Pygame에서 오류가 보고되지 않지만 내 그래픽이 표시되지 않습니다. 이는 절전 기능으로 밝혀졌습니다. 이를 비활성화하기 위해 Pygame/SDL이 초기화되기 전에 실행되는 다음 Python 코드를 추가했습니다.
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
행동을 취하다
/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>
당신은 그것을 사용할 수 있습니다사용자 모드필요한 경우 명령을 사용하여 위의 모든 그룹에 사용자를 추가할 수도 있습니다.
답변3
최근 경험에 따르면 (위에서 언급한 대로) tty 장치에 권한을 부여하는 것 외에도 다음 두 가지 작업을 수행해야 합니다.
- 실행 파일에 cap_sys_tty_config 기능을 부여합니다. Python 프로그램을 사용하는 경우 이를 수행할 수 있습니다
setcap cap_sys_tty_config+eip /usr/bin/python3.5
(Python의 경로를 사용자의 경로로 바꾸십시오). 물론, 이 기능을 모든 Python 스크립트에 부여한다는 점을 고려하세요. - 예를 들어 openvt를 사용하여 새 가상 터미널에서 프로세스를 실행합니다.
openvt ./your_script.py