All links of one day
in a single page.
<Previous day - Next day>

rss_feedDaily RSS Feed
floral_left The Daily Shaarli floral_right
——————————— March 30, 2018 - Friday 30, March 2018 ———————————

Si un programme affiche cette erreur, ou si incrond affiche l'erreur « Inotify::Inotify(): inotify init failed », et qu'il est normal que cette machine ait autant de fichiers ouverts et/ou suivis par inotify, alors on peut augmenter le nombre maximal de fichiers surveillés par inotify avec la commande sysctl -w fs.inotify.max_user_instances=256. La valeur "standard" est 128. On peut bien sûr pérenniser ceci dans un fichier posé dans /etc/sysctl.d.

ÉDIT DU 06/04/2018 À 13H25 : le paramètre à modifier est fs.inotify.max_user_instances, pas fs.inotify.max_user_watches ! FIN DE L'ÉDIT.

J'ai un ordinateur portable avec une station d'accueil. Sur cette station d'accueil, je branche un casque audio + micro USB. Il m'arrive très souvent de débrancher cet ordinateur portable de sa station d'accueil. À chaque rebranchement, je suis obligé de refaire la configuration PulseAudio afin de définir mon casque et son micro comme périphérique de sortie et d'entrée. Ce n'est plus possible, il faut rendre ça automatique.

La méthode consistant à utiliser udev pour passer des commandes à PulseAudio via pamcmd ou pactl ne fonctionne plus. Avant, il suffisait de lancer un script udev qui se fork en arrière-plan, ce qui permettait à PulseAudio de continuer son déroulement, donc de détecter le matériel audio puis à notre script de passer des commandes PulseAudio concernant ce matériel. Désormais, au moins dans Debian Stretch, l'implémentation habituelle d'udev est remplacée par celle de systemd-udevd. Ainsi, un fork (+ sleep) est désormais pris en compte par systemd-udevd et bloque la découverte du matériel par PulseAudio. Cela se constate avec sudo systemctl status udev.service (on constate l'arborescence des processus sous systemd-udevd, dont notre sleep).

Passons à la méthode que j'utilise :

  • On crée le fichier ~/.config/pulse/default.pa avec le contenu suivant :

    .include /etc/pulse/default.pa
    load-module module-switch-on-connect


  • On fait prendre en compte cette modif' par PulseAudio : pactl load-module module-switch-on-connect ;

  • À partir d'ici, PulseAudio basculera automatiquement sur tout nouveau périphérique audio qui sera connecté. Le dernier périphérique audio branché à un instant T sera celui qui sera utilisé. En entrée comme en sortie. Or, mon dock monte aussi un périphérique audio (probablement lié au port HDMI). Si jamais cette interface monte après mon casque, PulseAudio l'utilisera. Nous allons empêcher cela via un script udev dans /usr/local/bin/headset-delay.sh :

    #!/bin/bash
    logger -t /usr/local/bin/headset-delay.sh HEADSET ON
    sleep 2
    logger -t /usr/local/bin/headset-delay.sh HEADSET CONFIGURED


  • On rend ce script exécutable : sudo chmod +x /usr/local/bin/headset-delay.sh ;

  • On ajoute une règle udev qui exécute le script précédent dès que le casque est branché dans /etc/udev/rules.d/01-headset.rules (les ID se trouvent dans /var/log/kern.log quand on branche le casque) :

    ACTION=="add", ATTR{idVendor}=="1395", ATTR{idProduct}=="0029", RUN+="/usr/local/bin/headset-delay.sh"


  • Profit!

Plein de bonnes choses sur inotify et incrond. Notamment :

  • « Si les commandes sont exécutées plusieurs fois lors de la modification d’un fichier, c’est peut-être que le masque (le type d’événement surveillé) n’est pas tout à fait adapté. Vous pouvez empêcher l’exécution multiple en ajoutant au masque l’option « IN_NO_LOOP » qui désactive la notification d’événement tant que la première commande lancée n’est pas terminée :

  • Il est possible de passer des arguments à la commande lancée par incrond (exemple du manuel : « /tmp IN_ALL_EVENTS abcd $@/$# $% -> The first line monitors all events on the /tmp directory. When an event occurs it runs a application called 'abcd' with the full path of the file as the first arguments and the event flags as the second one. ») :
    • $@ : chemin complet du fichier/répertoire surveillé ;
    • $# : nom du fichier/répertoire sur lequel l’événement est intervenu ;
    • $% : nom (textuel) de l’événement intervenu ;
    • $& : numéro de l’événement intervenu ;
    • $$ : le caractère dollar (« $ ») ;

Je veux utiliser inotify pour surveiller les modifications du contenu d'un fichier. L'objectif est de lancer un script de vérification sémantique sur ce fichier et de les faire remonter aux admins via l’envoi d’un mail. Une erreur sémantique est une erreur qui ne plantera pas le démon/programme qui lit son fichier de conf’, mais qui empêchera d'atteindre le service attendu.

Pour ce faire, j'utilise incrond, donc j’ai ceci dans incrontab -e : <chemin_vers_fichier> IN_MODIFY <programme>.

Ça fonctionne sur le vif, mais plus après quelques semaines… Je relance le démon avec service incron restart. Ça fonctionne à nouveau… pour quelque temps seulement…

Explication : les éditeurs de texte en ligne de commande sérieux (vim, emacs, etc.) ne modifient jamais un fichier. L’événement inotify « IN_MODIFY » n’est donc jamais levé.

En effet, ils créent un fichier temporaire contenant le nouveau contenu puis ils déplacent ce fichier temporaire à l'emplacement du fichier visé par les modifications. L'objectif est de garantir l'absence de corruption du fichier modifié. En effet, mv (et l'appel système sous-jacent, rename) est la seule opération atomique sur un même système de fichiers : tant que le fichier reste au sein d'un même système de fichiers, mv consiste simplement à changer l'inode associé à un nom de fichier dans la liste des fichiers d'un dossier, et à virer l'ancienne entrée nom+inode.

Forcément, cette opération change l’inode (identifiant numérique d'un fichier dans la table des fichiers d'un système de fichiers) pointé par un nom de fichier dans la liste des fichiers d'un dossier. On peut vérifier cette hypothèse en exécutant un ls -lhi <fichier> avant et après la modification. Cela fait qu’inotify n’émet plus d’événements pour ce fichier qui a disparu, donc mon script n'est pas lancé par incrond.

Solution :

  • inotify fourni un événement, « IN_IGNORED », qui est envoyé par Linux quand un fichier disparaît. D'après mes tests, incrond ne prend pas en charge cet événement ;

  • inotify permet de surveiller la suppression d'un fichier (« IN_DELETE_SELF ») ou son déplacement (« IN_MOVE_SELF »). D'après mes tests, « IN_MOVE_SELF » fonctionne mieux avec vim que « IN_DELETE_SELF ».

Sans grande surprise, j’ai choisi la deuxième solution, donc ma ligne dans incrontab devient : <chemin_vers_fichier> IN_MODIFY,IN_MOVE_SELF <programme>. « IN_MODIFY » pour surveiller les modifs effectuées à l'arrache (echo, redirection shell, nano, etc.) et « IN_MOVE_SELF » pour les autres modifs (vim, etc.).

Merci Gradator pour le rappel sur le comportement des "vrais" éditeurs de texte. :)

-