(ルートとして実行されていない)SDLアプリにコンソールを使用させるには


14

SDLベースのプログラムを使用して、コンソールからログオンする必要なく、またルートとしてプログラムを実行せずに、グラフィックをコンソールに表示したい。たとえば、私はそれをssh経由で実行できるようにしたい。ターゲットOSは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呼び出しで分岐します-失敗はここに示されています。ioctlは、プログラムがコンソールから実行されるか、rootとしてsshから実行されると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

回答:


3

私の目的は元のポスターの目的と同じでしたが、1つの違いがありました。SDLアプリケーションをsystemdデーモンとして実行する必要がありました。私のLinuxマシンはRaspberry Pi 3で、オペレーティングシステムはRaspbian Jessieです。RPiに接続されたキーボードまたはマウスはありません。SSHを使用して接続します。私のSDLアプリは、実際にはPygameベースのアプリです。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〜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アプリケーションがキーボードイベントとマウスイベントを受信できるかどうかをテストしなかったことに注意してください。

ボーナス

私も興味があるかもしれない別の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. Raspberry PiのHDMI出力に接続された約10分後に画面が黒くなりましたが(電源はオフになりませんでした)、グラフィックは表示されませんでしたが、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
    

1
これは、Piにキーボードを接続せずにpygameを開始するのに非常に役立ちました。ありがとうございます。pygameを実行し、カーソルの/dev/tty7問題ExecStartPre=/bin/chvt 7を回避するためにを発行するのに十分簡単であり、tty1〜tty6でデフォルトで実行されるagettyと衝突しないというボーナスがあります。
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 / console

グループは「ルート」ですが、グループアクセスは許可されていません。ルートグループにアクセス許可を追加するのは好きではないので、代わりにグループを作成してファイルを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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.