web-dev-qa-db-fra.com

Lancer l'application (GUI) lors du montage de tout périphérique USB

J'utilise Ubuntu-gnome 16.04 LTS 4.4.0-62-generic.

Je voudrais faire la suite: Run soit ...

  • (a) une application (GUI) [/path/to/my_app.desktop]
  • ou (b) un script interactif dans un terminal [par exemple: $ gnome-terminal -x /path/to/script.sh]

... chaque fois qu'un montage de tout (USB) périphérique est reconnu.

L'exécution sur le serveur X de l'utilisateur semble obligatoire, car il est nécessaire de modifier les entrées de l'utilisateur en réponse à l'application/au script en cours d'exécution. il ne peut pas simplement fonctionner en arrière-plan.

Au cours des 2 derniers jours, j'ai effectué des recherches approfondies et expérimenté les deux, udev-rules et systemd.services . Le problème récurrent est que l'une ou l'autre de ces dernières approches nécessite l'authentification X . Bien qu'il existe des moyens (compliqués) de rendre l'authentification effective, je n'aime pas l'idée de violer la sécurité du système inné en exportant les variables $ XAUTHORITY de la racine à la session de l'utilisateur ...

Je suppose qu'il devrait y avoir une autre façon de faire ce qui suit:

  1. détecter quand/si un nouveau périphérique (USB) a été monté
  2. démarrer une application/un script (dans le terminal) avec les privilèges USER sur le bureau de l'utilisateur (par exemple, Xsession de l'utilisateur?)
  3. (facultatif: transmettez le nom de périphérique en tant que variable)

(création de fichiers .config spécifiques au montage ?; org.gnome.desktop.media-manipulation ?; autostart-script observant/home/$ USERNAME/media .mounts ?; édition/etc/fstab; ...?)

Toute allusion serait hautement appréciée.

3
brunuser

(Ancienne réponse, nouvelle réponse plus bas)


Exécuter un script ou une commande à exécuter chaque fois qu'un lecteur USB est connecté

Si, pour une raison quelconque, vous ne souhaitez pas utiliser les règles udev ou quelque chose de plus compliqué, utilisez le script ci-dessous.

Exécuter simplement le script, avec votre commande à exécuter en argument, fera le travail.

Le scénario:

#!/usr/bin/env python3
import subprocess
import time
import sys

cmd = " ".join(sys.argv[1:])

def get_mountedlist():
    return [(item.split()[0].replace("├─", "").replace("└─", ""),
             item[item.find("/"):]) for item in subprocess.check_output(
            ["/bin/bash", "-c", "lsblk"]).decode("utf-8").split("\n") if "/" in item]

def identify(disk):
    command = "find /dev/disk -ls | grep /"+disk
    return "usb" in subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

mounted1 = get_mountedlist()
while True:
    time.sleep(4)
    mounted2 = get_mountedlist()
    if [d for d in mounted2 if all([not d in mounted1, d != "/", identify(d[0]) == True])]:
        subprocess.Popen(["/bin/bash", "-c", cmd])
    mounted1 = mounted2

Utiliser

  1. Copiez le script dans un fichier vide, enregistrez-le sous le nom run_usbactions.py
  2. Testez le script en exécutant (par exemple) la commande:

    python3 /path/to/run_usbactions.py <command_to_run> <optional_args>
    

    Dans mon test, j'ai utilisé par exemple:

    python3 /path/to/run_usbactions.py gedit file
    

    pour ouvrir file avec gedit une fois le lecteur USB connecté.

  3. Si tout fonctionne correctement, ajoutez-le à Applications de démarrage: Dash> Applications de démarrage> Ajouter. Ajoutez la commande:

    python3 /path/to/run_usbactions.py <command_to_run> <optional_args>
    

Explication

  • Une fois toutes les quatre secondes, dans la fonction get_mountedlist(), le script lit le résultat de lsblk.

  • Dans le cas où supplémentaire des partitions ou des périphériques sont montés, la sortie de (par exemple) la commande:

    find /dev/disk -ls | grep sdc1
    

    inclura la chaîne usb et identifiera le lecteur monté en tant que lecteur USB.
    En le regardant maintenant, je pourrais très bien le remplacer par une méthode plus "pythonique", plutôt que par un appel système, mais comme je l’ai copié à partir d’un script plus ancien, je ne l’ai pas (encore) .

  • ensuite, if le nouveau lecteur est un usb, la commande (+ arguments possibles), telle que définie dans " ".join(sys.argv[1:]) est exécutée.




MODIFIER

(29 décembre 2017)

Utiliser pyudev

Depuis que j'ai "rencontré" Pyudev, je pensais que je devrais partager la simplification majeure et le fonctionnement plus clair qu'elle apporte. Un script simple pour effectuer toute action lors de l'insertion d'un périphérique USB devient alors:

#!/usr/bin/env python3
import pyudev
import subprocess
import sys

cmd = " ".join(sys.argv[1:])

monitor = pyudev.Monitor.from_netlink(pyudev.Context())
monitor.filter_by('block')

for device in iter(monitor.poll, None):
    if all([
        device['ACTION'] == "add", 'ID_FS_TYPE' in device,
        device['ID_USB_DRIVER'] == "usb-storage",
        ]):
        print("added", device.get('ID_FS_LABEL'))
        subprocess.Popen(["/bin/bash", "-c", cmd])

Usage

Assurez-vous que pyudev est installé:

Sudo apt install python3-pyudev

Les autres instructions sont exactement similaires.

3
Jacob Vlijm