デバイスの権限を表示する(ここではubuntu 15.04)

デバイスの権限を表示する(ここではubuntu 15.04)

コンソールにログインしたり、プログラムを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

レシピ

  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
    

これは私にとって効果的です。パイゲームアプリケーションがキーボードとマウスイベントを受け取ることができるかどうかをテストしていないことに注意してください。

ボーナス

また、興味深いことがある他の2つの問題も解決する必要があります。

  1. フレームバッファグラフィックと一緒に画面下部に点滅するテキストカーソルがあります。この問題を解決するために、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
    
  2. 約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

関連情報