コンソールにログインしたり、プログラムをrootとして実行したりせずに、SDLベースのプログラムを使用してコンソールにグラフィックを表示したいと思います。たとえば、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)を作成し、自分のユーザーをそのグループに入れてから、グループに/ dev / tty0へのアクセスを許可するudevルールを追加しました。
strace 出力は、この ioctl 呼び出しから分岐します。これは、プログラムがコンソールまたはsshからrootとして実行されたときにioctlが0を返します。
open("/dev/tty", O_RDWR) = 4
ioctl(4, VT_GETSTATE, 0xbeaa01f8) = -1 EINVAL (Invalid argument)
(住所も異なりますが関係ありません。)
私のプログラムがrootとして実行されたときにうまく動作することを考えると、これは権限の問題があることを意味すると仮定します。コンソールにログインせずに(そしてrootとして実行せずに)このプログラムを実行できるようにユーザーに必要な権限を付与するにはどうすればよいですか?
答え1
私の目標は元のポスターの目標と同じですが、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
私のPygameパッケージのバージョンは:(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
これは私にとって効果的です。パイゲームアプリケーションがキーボードとマウスイベントを受け取ることができるかどうかをテストしていないことに注意してください。
ボーナス
また、興味深いことがある他の2つの問題も解決する必要があります。
フレームバッファグラフィックと一緒に画面下部に点滅するテキストカーソルがあります。この問題を解決するために、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デバイスに権限を付与することに加えて、次の2つのことを行う必要があります。
- 実行可能ファイルに cap_sys_tty_config 機能を付与します。 Pythonプログラムを使用している場合はこれを行うことができます
setcap cap_sys_tty_config+eip /usr/bin/python3.5
(Pythonのパスをユーザーのパスに置き換えます)。もちろん、この機能をすべてのPythonスクリプトに与えることを検討してください。 - たとえば、openvt を使用して新しい仮想端末でプロセスを実行します。
openvt ./your_script.py