Как я могу запускать код всякий раз, когда USB-устройство (не) подключено, не требуя прав root?
У меня есть скрипт, который я хочу запускать всякий раз, когда подключаю / отключаю мышь или клавиатуру к USB-порту.
Уже есть много документации о том, как настроить правила udev для запуска произвольных сценариев, когда устройство подключено или отключено. Но для настройки этих правил требуются права суперпользователя. И, хотя у меня есть root-доступ на моей машине, я ищу решение, которое не требует sudo, root или написания правил udev. (почему? потому что будет легче запускать, поддерживать и распространять)
Скорее всего, решение будет использовать dbus, но я могу ошибаться.
(Кстати, я и опытный пользователь, и бывший пользователь Gentoo, не стесняйтесь выкладывать технические детали!)
Решения, которые требуют root:
- Автозапуск сценария после того, как я подключил или отключил USB-устройство
- http://granjow.net/udev-rules.html
- http://hg.dfrank.ru/linux/my-udev-notify (из этого вопроса / ответа)
На первый взгляд устаревшие решения, которым не нужен root:
- В этом ответе предлагается каракатица, но последняя версия от 2012-08-24.
- В этой ветке предлагается halevt, но последняя версия от 2010-02-18.
- Этот вопрос / ответ указывает на это руководство, в котором имеется исходный код C++ с использованием устаревшего и устаревшего HAL.
1 ответ
В вопросе " Как я могу прослушать события" вставлено USB-устройство "в Linux, в Python? " Приведен очень короткий пример сценария Python с использованием pyudev. Этот сценарий может легко обнаружить, когда устройство подключено или отключено, отслеживая device-event
от usb
подсистема.
Более того, pyudev - это реализация на чистом python, доступная как на Python 2, так и на Python 3.
На основе этого примера кода я написал auto_exec_xinput_xset_upon_usb_device_change.py (см. Также самую последнюю версию). Работает как на Python 2, так и на Python 3.
#!/usr/bin/env python
import functools
import os.path
import pyudev
import subprocess
def main():
BASE_PATH = os.path.abspath(os.path.dirname(__file__))
path = functools.partial(os.path.join, BASE_PATH)
call = lambda x, *args: subprocess.call([path(x)] + list(args))
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='usb') # Remove this line to listen for all devices.
monitor.start()
for device in iter(monitor.poll, None):
# I can add more logic here, to run only certain kinds of devices are plugged.
call('foobar.sh')
if __name__ == '__main__':
main()