ディスプレイなしでキーボードを監視

ディスプレイなしでキーボードを監視

ラズベリーパイゼロで実行されているキーパッドとeインクディスプレイを使用するプロジェクト作業中です。私はPython用のいくつかのキーボードパッケージ(pynput、pyxhook)を試しましたが、デスクトップ(ubuntu)でうまく機能する簡単なキーロガーを作成/テストしました。

しかし、モニターなしでパイで実行しようとしたところ、両方のライブラリが死んでいました。

DisplayConnectionError: Can't connect to display ":0": [Errno 111] Connection refused

少なくともpyxhookがマウスの動きをキャプチャできることを知っているので、モニタへのアクセスが「必要」である理由が理解されます。しかし、私が望むのは、モニターが接続されていないままバックグラウンドで実行されるプロセスでキーボード入力をキャプチャする方法です。

これらのライブラリは、現在の主要イベントの一部としてフォーカスがあるウィンドウを返すこともできます。これは、おそらくモニターバインディングがそれほど深い理由です。私は前に試しました

$export DISPLAY=":0"

役に立ちません。

以下は、モニターでは機能しますが、ヘッドレス実行時(SSHで実行)は機能しない単純なpynputコードです。

#!/usr/bin/env python

from pynput import keyboard

def on_press(key):
    print('Key {} pressed.'.format(key))
    if str(key) == 'Key.esc':
        print('Exiting...')
        return False


with keyboard.Listener(on_press = on_press) as listener:
    listener.join()

これらのタスクを実行する方法はありますか?または、この問題を解決する別の方法があります。

上記のプログラム障害の完全なスタック追跡

Traceback (most recent call last):
  File "./keylog.py", line 3, in <module>
    from pynput import keyboard
  File "/usr/local/lib/python2.7/dist-packages/pynput/__init__.py", line 23, in <module>
    from . import keyboard
  File "/usr/local/lib/python2.7/dist-packages/pynput/keyboard/__init__.py", line 49, in <module>
    from ._xorg import KeyCode, Key, Controller, Listener
  File "/usr/local/lib/python2.7/dist-packages/pynput/keyboard/_xorg.py", line 38, in <module>
    from pynput._util.xorg import (
  File "/usr/local/lib/python2.7/dist-packages/pynput/_util/xorg.py", line 38, in <module>
    _check()
  File "/usr/local/lib/python2.7/dist-packages/pynput/_util/xorg.py", line 36, in _check
    display = Xlib.display.Display()
  File "/usr/local/lib/python2.7/dist-packages/Xlib/display.py", line 89, in __init__
    self.display = _BaseDisplay(display)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/display.py", line 71, in __init__
    protocol_display.Display.__init__(self, *args, **keys)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/protocol/display.py", line 90, in __init__
    self.socket = connect.get_socket(name, protocol, host, displayno)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/support/connect.py", line 87, in get_socket
    return mod.get_socket(dname, protocol, host, dno)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/support/unix_connect.py", line 113, in get_socket
    raise error.DisplayConnectionError(dname, str(val))
Xlib.error.DisplayConnectionError: Can't connect to display ":0": [Errno 111] Connection refused

答え1

さて、調べて答えを投稿すると思いました。

Pythonsキーボードモジュール、ドキュメント、ソースコードここ

「既知の制限事項」セクションで述べたように(これは制限事項ではないと思いますが!)

「Xに依存しないために、Linux部分はrawデバイスファイル(/dev/input/input*)を読み込みますが、これにはrootが必要です。」

したがって、プログラムは現在root権限を必要とするため、これは明らかにセキュリティ上の問題を引き起こしますが、私が知っている限り問題ではありません。

pip install keyboard

簡単な手順

import keyboard
import time

def key_press(key):
    print(key.name)

keyboard.on_press(key_press)

while True:
    time.sleep(1)

答え2

現在、同様の問題を解決しています。私はこの問題を解決する方法を知っています。しかし、まだ試していません。これを新しい質問に入れるかどうかはわかりません。

  • ユーザーを自動的にログインする仮想コンソールの設定
  • コンソールはインタラクティブシェルを表示しませんが、キーを押してMPDに送信するだけです。

それはすべてです。それでもCtrl-Fxを使用して標準コンソールに切り替えて、不要なMPD制御などの副作用なしに正常にログインできます。

まだ解決されていないいくつかの問題があります。

  • モニタが接続されていない場合、Linuxで仮想コンソールを開くことはできますか?

  • このコンソールを設定するには? /etc/login.defs?

  • リスナープロセスではどの言語とライブラリを使用しますか(これまではすべてをPythonとして実装しました)

  • MPDにイベントを渡す方法(mpcコマンドラインクライアントまたはPython mpcクライアントライブラリを介して?)

これをコミュニティウィキで表示します。したがって、誰でもこの回答に自由に貢献できます。

背景:現在、GPIOピンを介して制御されているMPDを使用してRaspberry Piにヘッドレスオーディオプレーヤーを実装しています。これでキーボードでもコントロールできるようになってほしいです。

関連情報