디스플레이 없이 키보드 모니터링

디스플레이 없이 키보드 모니터링

라즈베리 파이 제로에서 실행되는 키패드와 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 부분은 원시 장치 파일(/dev/input/input*)을 읽습니다. 하지만 이를 위해서는 루트가 필요합니다."

따라서 프로그램에 이제 루트 권한이 필요하므로 이로 인해 분명히 보안 문제가 발생하지만 제가 아는 한 문제는 아닙니다.

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

현재 비슷한 문제를 해결하고 있습니다. 나는 이 문제를 해결하는 방법을 알고 있습니다. 하지만 아직 시도하지 않았습니다. 이것을 새로운 질문에 넣어야할지 잘 모르겠습니다.

  • 사용자를 자동으로 로그인하는 가상 콘솔 설정
  • 콘솔은 대화형 셸(bash)을 표시하지 않지만 키 누르기를 수신하여 MPD로 보내는 프로세스일 뿐입니다.

그게 다야. 여전히 Ctrl-Fx를 사용하여 표준 콘솔로 전환하고 불필요한 MPD 제어 등의 부작용 없이 정상적으로 로그인할 수 있습니다.

아직 해결되지 않은 몇 가지 문제가 있습니다.

  • 모니터가 연결되어 있지 않으면 Linux에서 가상 콘솔을 열 수 있습니까?

  • 이 콘솔을 설정하는 방법은 무엇입니까? /etc/login.defs?

  • 리스너 프로세스에서는 어떤 언어와 라이브러리를 사용합니까(지금까지는 모든 것을 Python으로 구현했습니다)

  • MPD에 이벤트를 전달하는 방법 (mpc 명령줄 클라이언트 또는 Python mpc 클라이언트 라이브러리를 통해?)

이것을 커뮤니티 위키로 표시하겠습니다. 따라서 누구나 이 답변에 자유롭게 기여할 수 있습니다.

배경: 현재 GPIO 핀을 통해 제어되는 MPD를 사용하여 Raspberry Pi에 헤드리스 오디오 플레이어를 구현했습니다. 이제 키보드로도 제어할 수 있게 되었으면 좋겠습니다.

관련 정보