6

I have a script that I wish to run whenever I plug/unplug a mouse or keyboard to my USB port.

There is already plenty of documentation on how to configure udev rules to run arbitrary scripts when a device is plugged or unplugged. But configuring those rules requires root permissions. And, although I do have root access on my machine, I'm looking for a solution that does not require sudo, root, or writing udev rules. (why? because it will be easier to run, maintain and distribute)

Most likely, the solution will use dbus, but I might be mistaken.

(By the way, I'm and advanced user and former Gentoo user, feel free to spit out technical details!)


Solutions that require root:

Seemingly outdated solutions that don't need root:

  • http://askubuntu.com/questions/159007/how-do-i-run-specific-sudo-commands-without-a-password could help? – Tim Aug 26 '14 at 15:11
  • "(why? because it will be easier to run, maintain and distribute)" I would include "easier to abuse". If anyone could hook a script onto an USB device it would be far too easy to abuse. You probably will need sudo/root to set this up (and circumventing like @Tim suggest is also using root ;) ) – Rinzwind Aug 26 '14 at 15:11
  • @Rinzwind it would need it for set up - but most things do, like installing any program - that ^^ doesn't need root each time, or each startup.... – Tim Aug 26 '14 at 15:14
  • @Tim solution is overkill. It is a nice feature, indeed, but overkill. Essentially, I want to run some xset and xinput commands to reconfigure my mice and touchpad whenever one of them gets connected. – Denilson Sá Maia Aug 26 '14 at 15:18
  • What do you want it to do with the information that one has been unplugged? Would a script running every 30 secs comparing the difference between xinput then and now work? – Tim Aug 26 '14 at 15:22
  • @Tim: this is a laptop. I don't want a script running every couple of seconds. And 30 seconds between mouse-plugging and it working correctly (sensibility settings) is too long. The best solution is to use some kind of event or signal, so the code only runs when something actually changes, instead of polling. – Denilson Sá Maia Aug 26 '14 at 15:27

1 Answers1

6

The "How can I listen for 'usb device inserted' events in Linux, in Python?" question has a very short sample Python script using pyudev. That script can easily detect when a device is connected or disconnected, by monitoring the device-event from the usb subsystem.

What's more, pyudev is pure-python implementation and is available on both Python 2 and Python 3.

Based on that sample code, I've written auto_exec_xinput_xset_upon_usb_device_change.py (see also the most recent version). Works on both Python 2 and 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()
  • Hey! how do I run your script in the background on startup and whenever a USB device is being inserted it's going to look for a certain file in it, update.sh for example, and if it exists it will execute it? – kfirba Sep 04 '15 at 09:27
  • Running in background on startup: depends on your system. Read: https://askubuntu.com/q/48321 https://askubuntu.com/q/30931 https://askubuntu.com/q/459277 http://askubuntu.com/a/458262 Checking if a file exists in Python: https://stackoverflow.com/q/82831 Running it: call('update.sh') or call('bash', 'update.sh') (because I've defined the call() function in the code from my answer). – Denilson Sá Maia Sep 04 '15 at 12:53