Une introduction à Udev : le sous-système Linux de gestion des événements de périphériques

Udev est le sous-système Linux qui alimente votre ordinateur en événements de périphériques. En clair, cela signifie que c’est le code qui détecte quand vous avez des choses branchées sur votre ordinateur, comme une carte réseau, des disques durs externes (y compris les clés USB), des souris, des claviers, des joysticks et des manettes de jeu, des lecteurs de DVD-ROM, etc. Cela en fait un utilitaire potentiellement utile, et il est suffisamment bien exposé pour qu’un utilisateur standard puisse le scénariser manuellement pour faire des choses comme exécuter certaines tâches lorsqu’un certain disque dur est branché.

Cet article vous apprend à créer un script udev déclenché par un certain événement udev, comme le branchement d’une clé USB spécifique. Une fois que vous comprenez le processus de travail avec udev, vous pouvez l’utiliser pour faire toutes sortes de choses, comme charger un pilote spécifique lorsqu’une manette de jeu est connectée, ou effectuer une sauvegarde automatique lorsque vous attachez votre disque de sauvegarde.

Un script de base

La meilleure façon de travailler avec udev est par petits morceaux. N’écrivez pas tout le script au départ, mais commencez plutôt par quelque chose qui confirme simplement qu’udev déclenche un certain événement personnalisé.

Selon votre objectif pour votre script, vous ne pouvez pas garantir que vous verrez jamais les résultats d’un script de vos propres yeux, alors assurez-vous que votre script consigne qu’il a été déclenché avec succès. L’endroit habituel pour les fichiers journaux est le répertoire /var, mais c’est surtout le domaine de l’utilisateur root. Pour les tests, utilisez /tmp, qui est accessible par les utilisateurs normaux et qui est généralement nettoyé lors d’un redémarrage.

Ouvrez votre éditeur de texte préféré et entrez ce script simple :

#!/usr/bin/bash
/usr/bin/date >> /tmp/udev.log

Placez-le dans /usr/local/bin ou un endroit de ce type dans le chemin d’exécution par défaut. Appelez-le trigger.sh et, bien sûr, rendez-le exécutable avec chmod +x.

$ sudo mv trigger.sh /usr/local/bin
$ sudo chmod +x /usr/local/bin/trigger.sh

Ce script n’a rien à voir avec udev. Lorsqu’il s’exécute, le script place un horodatage dans le fichier /tmp/udev.log. Testez vous-même le script :

$ /usr/local/bin/trigger.sh
$ cat /tmp/udev.log
Tue Oct 31 01:05:28 NZDT 2035

L’étape suivante consiste à faire en sorte que udev déclenche le script.

Identification unique du périphérique

Pour que votre script soit déclenché par un événement du périphérique, udev doit savoir dans quelles conditions il doit appeler le script. Dans la vie réelle, vous pouvez identifier une clé USB par sa couleur, son fabricant et le fait que vous venez de la brancher sur votre ordinateur. Votre ordinateur, cependant, a besoin d’un ensemble différent de critères.

Udev identifie les périphériques par des numéros de série, des fabricants, et même des numéros d’identification de vendeur et de produit. Puisque c’est tôt dans la vie de votre script udev, soyez aussi large, non spécifique et inclusif que possible. En d’autres termes, vous voulez d’abord attraper presque tout événement udev valide pour déclencher votre script.

Avec la commande udevadm monitor, vous pouvez exploiter udev en temps réel et voir ce qu’il voit lorsque vous branchez différents périphériques. Devenez root et essayez-le.

$ su
# udevadm monitor

La fonction monitor imprime les événements reçus pour :

  • UDEV : l’événement qu’udev envoie après le traitement des règles
  • KERNEL : l’uevent du noyau

Avec udevadm monitor en cours d’exécution, branchez une clé USB et observez toutes sortes d’informations crachées sur votre écran. Remarquez que le type d’événement est un événement ADD. C’est une bonne façon d’identifier le type d’événement que vous voulez.

La commande udevadm monitor fournit beaucoup de bonnes informations, mais vous pouvez les voir avec un formatage plus joli avec la commande udevadm info, en supposant que vous savez où votre clé USB est actuellement située dans votre arbre /dev. Si ce n’est pas le cas, débranchez et rebranchez votre clé USB, puis lancez immédiatement cette commande :

$ su -c 'dmesg | tail | fgrep -i sd*'

Si cette commande renvoie sdb : sdb1, par exemple, vous savez que le noyau a attribué à votre clé USB l’étiquette sdb.

Alternativement, vous pouvez utiliser la commande lsblk pour voir tous les lecteurs attachés à votre système, y compris leurs tailles et leurs partitions.

Maintenant que vous avez établi où votre lecteur est situé dans votre système de fichiers, vous pouvez afficher les informations udev sur ce périphérique avec cette commande:

# udevadm info -a -n /dev/sdb | less

Cela renvoie beaucoup d’informations. Concentrez-vous sur le premier bloc d’informations pour le moment.

Votre travail consiste à choisir les parties du rapport d’udev sur un périphérique qui sont les plus uniques à ce périphérique, puis à dire à udev de déclencher votre script lorsque ces attributs uniques sont détectés.

Le processus udevadm info fait un rapport sur un périphérique (spécifié par le chemin du périphérique), puis « remonte » la chaîne des périphériques parents. Pour chaque périphérique trouvé, il imprime tous les attributs possibles en utilisant un format clé-valeur. Vous pouvez composer une règle pour correspondre selon les attributs d’un périphérique plus les attributs d’un seul périphérique parent.

looking at device '/devices/000:000/blah/blah//block/sdb':
KERNEL=="sdb"
SUBSYSTEM=="block"
DRIVER==""
ATTR{ro}=="0"
ATTR{size}=="125722368"
ATTR{stat}==" 2765 1537 5393"
ATTR{range}=="16"
ATTR{discard\_alignment}=="0"
ATTR{removable}=="1"
ATTR{blah}=="blah"

Une règle udev doit contenir un attribut d’un seul périphérique parent.

Les attributs parentaux sont des choses qui décrivent un périphérique à partir du niveau le plus basique, comme c’est quelque chose qui a été branché dans un port physique ou c’est quelque chose avec une taille ou c’est un périphérique amovible.

Puisque l’étiquette KERNEL de sdb peut changer en fonction du nombre d’autres lecteurs qui ont été branchés avant que vous ne branchiez cette clé USB, ce n’est pas l’attribut parent optimal pour une règle udev. Cependant, cela fonctionne pour une preuve de concept, donc vous pouvez l’utiliser. Un candidat encore meilleur est l’attribut SUBSYSTEM, qui identifie qu’il s’agit d’un périphérique système « bloc » (c’est pourquoi la commande lsblk répertorie le périphérique).

Ouvrez un fichier appelé 80-local.rules dans /etc/udev/rules.d et entrez ce code :

SUBSYSTEM=="block", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"

Enregistrez le fichier, débranchez votre clé USB de test et redémarrez.

Attendez, redémarrez sur une machine Linux ?

Théoriquement, vous pouvez juste émettre udevadm control –reload, qui devrait charger toutes les règles, mais à ce stade du jeu, il est préférable d’éliminer toutes les variables. Udev est suffisamment complexe, et vous ne voulez pas rester au lit toute la nuit en vous demandant si cette règle n’a pas fonctionné à cause d’une erreur de syntaxe ou si vous auriez simplement dû redémarrer. Donc redémarrez sans tenir compte de ce que votre fierté POSIX vous dit.

Lorsque votre système est de nouveau en ligne, passez à une console texte (avec Ctl+Alt+F3 ou similaire) et branchez votre clé USB. Si vous exécutez un noyau récent, vous verrez probablement un tas de sorties dans votre console lorsque vous brancherez le lecteur. Si vous voyez un message d’erreur tel que Could not execute /usr/local/bin/trigger.sh, vous avez probablement oublié de rendre le script exécutable. Sinon, avec un peu de chance, tout ce que vous voyez est qu’un périphérique a été branché, il a obtenu une sorte d’affectation de périphérique du noyau, et ainsi de suite.

Maintenant, le moment de vérité:

$ cat /tmp/udev.log
Tue Oct 31 01:35:28 NZDT 2035

Si vous voyez une date et une heure très récentes renvoyées par /tmp/udev.log, udev a réussi à déclencher votre script.

Raffiner la règle en quelque chose d’utile

Le problème avec cette règle est qu’elle est très générique. Brancher une souris, une clé USB, ou la clé USB de quelqu’un d’autre déclenchera indistinctement votre script. Il est maintenant temps de commencer à se concentrer sur la clé USB exacte que vous voulez déclencher votre script.

Une façon de le faire est avec l’ID du vendeur et l’ID du produit. Pour obtenir ces numéros, vous pouvez utiliser la commande lsusb.

$ lsusb
Bus 001 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 002 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 003 Device 005: ID 03f0:3307 TyCoon Corp.
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 hub
Bus 001 Device 003: ID 13d3:5165 SBo Networks

Dans cet exemple, le 03f0:3307 devant TyCoon Corp. désigne les attributs idVendor et idProduct. Vous pouvez également voir ces numéros dans la sortie de udevadm info -a -n /dev/sdb | grep vendor, mais je trouve la sortie de lsusb un peu plus facile à regarder.

Vous pouvez maintenant inclure ces attributs dans votre règle.

SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/thumb.sh"

Testez cela (oui, vous devriez toujours redémarrer, juste pour vous assurer que vous obtenez des réactions fraîches de la part d’udev), et cela devrait fonctionner de la même manière qu’avant, seulement maintenant si vous branchez, disons, une clé USB fabriquée par une société différente (donc avec un idVendor différent) ou une souris ou une imprimante, le script ne sera pas déclenché.

Continuez à ajouter de nouveaux attributs pour vous concentrer davantage sur cette unique clé USB que vous voulez déclencher votre script. En utilisant udevadm info -a -n /dev/sdb, vous pouvez trouver des choses comme le nom du vendeur, parfois un numéro de série, ou le nom du produit, et ainsi de suite.

Pour votre propre santé mentale, assurez-vous d’ajouter seulement un nouvel attribut à la fois. La plupart des erreurs que j’ai faites (et j’ai vu d’autres personnes en ligne faire) est de jeter un tas d’attributs dans leur règle udev et de se demander pourquoi la chose ne fonctionne plus. Tester les attributs un par un est le moyen le plus sûr de s’assurer qu’udev peut identifier votre périphérique avec succès.

Sécurité

Cela fait apparaître les problèmes de sécurité liés à l’écriture de règles udev pour faire automatiquement quelque chose lorsqu’un lecteur est branché. Sur mes machines, je n’ai même pas l’auto-montage activé, et pourtant cet article propose des scripts et des règles qui exécutent des commandes juste en ayant quelque chose de branché.

Deux choses à garder à l’esprit ici.

  1. Focalisez vos règles udev une fois que vous les avez fait fonctionner afin qu’elles ne déclenchent des scripts que lorsque vous le voulez vraiment. L’exécution d’un script qui copie aveuglément des données vers ou depuis votre ordinateur est une mauvaise idée au cas où quelqu’un qui se trouve être porteur de la même marque de clé USB la branche sur votre ordinateur.
  2. Ne rédigez pas votre règle udev et vos scripts et oubliez-les. Je sais quels ordinateurs ont mes règles udev, et ces boîtes sont le plus souvent mes ordinateurs personnels, pas ceux que j’emmène à des conférences ou que j’ai dans mon bureau au travail. Plus un ordinateur est  » social « , moins il a de chances d’avoir une règle udev sur lui qui pourrait potentiellement aboutir à ce que mes données se retrouvent sur l’appareil de quelqu’un d’autre ou les données de quelqu’un d’autre ou un logiciel malveillant sur mon appareil.

En d’autres termes, comme pour une grande partie du pouvoir fourni par un système GNU, c’est votre travail d’être attentif à la façon dont vous exercez ce pouvoir. Si vous en abusez ou si vous ne le traitez pas avec respect, cela pourrait très bien mal tourner.

Udev dans le monde réel

Maintenant que vous pouvez confirmer que votre script est déclenché par udev, vous pouvez porter votre attention sur la fonction du script. Pour l’instant, il est inutile, ne faisant rien de plus que de consigner le fait qu’il a été exécuté.

J’utilise udev pour déclencher des sauvegardes automatisées de mes disques de pouce. L’idée est que les copies maîtresses de mes documents actifs sont sur ma clé USB (puisqu’elle va partout où je vais et pourrait être travaillée à tout moment), et ces documents maîtres sont sauvegardés sur mon ordinateur chaque fois que je branche la clé sur cette machine. En d’autres termes, mon ordinateur est le disque de sauvegarde et mes données de production sont mobiles. Le code source est disponible, alors n’hésitez pas à regarder le code de attachup pour d’autres exemples de contrainte de vos tests udev.

Puisque c’est ce pour quoi j’utilise le plus udev, c’est l’exemple que je vais utiliser ici, mais udev peut saisir beaucoup d’autres choses, comme les manettes de jeu (c’est utile sur les systèmes qui ne sont pas configurés pour charger le module xboxdrv lorsqu’une manette de jeu est attachée) et les caméras et les microphones (utiles pour définir les entrées lorsqu’un micro spécifique est attaché), alors réalisez qu’il est bon pour beaucoup plus que cet exemple.

Une version simple de mon système de sauvegarde est un processus à deux commandes :

SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", SYMLINK+="safety%n"
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"

La première ligne détecte ma clé USB avec les attributs déjà discutés, puis assigne à la clé USB un lien symbolique dans l’arborescence des périphériques. Le lien symbolique qu’elle attribue est safety%n. Le %n est une macro udev qui se résout en n’importe quel numéro que le noyau donne au périphérique, comme sdb1, sdb2, sdb3, et ainsi de suite. Donc %n serait le 1 ou le 2 ou le 3.

Cela crée un lien symbolique dans l’arbre dev, donc cela n’interfère pas avec le processus normal de branchement d’un périphérique. Cela signifie que si vous utilisez un environnement de bureau qui aime monter automatiquement les périphériques, vous ne lui causerez pas de problèmes.

La deuxième ligne exécute le script.

Mon script de sauvegarde ressemble à ceci :

#!/usr/bin/bash
mount /dev/safety1 /mnt/hd
sleep 2
rsync -az /mnt/hd/ /home/seth/backups/ && umount /dev/safety1

Le script utilise le lien symbolique, ce qui évite la possibilité qu’udev nomme le lecteur de manière inattendue (par exemple, si j’ai une clé USB appelée DISK déjà branchée sur mon ordinateur, et que je branche mon autre clé USB également appelée DISK, la seconde sera étiquetée DISK_, ce qui ferait échouer mon script). Il monte safety1 (la première partition du lecteur) à mon point de montage préféré de /mnt/hd.

Une fois monté en toute sécurité, il utilise rsync pour sauvegarder le lecteur dans mon dossier de sauvegarde (mon script actuel utilise rdiff-backup, et le vôtre peut utiliser n’importe quelle solution de sauvegarde automatisée que vous préférez).

Udev est votre dev

Udev est un système très flexible et vous permet de définir des règles et des fonctions d’une manière que peu d’autres systèmes osent fournir aux utilisateurs. Apprenez-le et utilisez-le, et profitez de la puissance de POSIX.

Cet article s’appuie sur le contenu du manuel Slackermedia, qui est sous licence GNU Free Documentation License 1.3.

.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.