Exploiter inotify, c’est simple

93
24
nov.
2014
Linux

Intégré à partir de Linux 2.6.13, le mécanisme inotify permet de mettre en place des actions associées à l’évolution de l’état du système de fichiers. À l’occasion des 10 ans de ce projet, cette dépêche va vous donner des pistes pour exploiter ce mécanisme qui pourra vous simplifier bien des tâches d’administration.

Sommaire

Description du fonctionnement

Le mécanisme inotify permet de positionner un watch descriptor sur un fichier, qui enverra des notifications au système lorsque des événements affecteront le fichier suivi. Pour rappel, dans le monde UNIX, un fichier peut aussi bien représenter un fichier simple qu’un répertoire, un périphérique, un lien, etc. Les principaux événements qui peuvent être suivis sont :

  • IN_ACCESS : le fichier est accédé en lecture ;
  • IN_MODIFY : le fichier est modifié ;
  • IN_ATTRIB : les attributs du fichiers sont modifiés ;
  • IN_OPEN : le fichier est ouvert ;
  • IN_CLOSE_WRITE : le fichier est fermé après avoir été ouvert en écriture ;
  • IN_CLOSE_NOWRITE : le fichier est fermé après avoir été ouvert en lecture ;
  • IN_MOVED_FROM / IN_MOVED_TO : le fichier a été déplacé ou renommé ;
  • IN_DELETE_SELF : le fichier a été supprimé ;
  • IN_DELETE : un fichier a été supprimé dans le répertoire surveillé ;
  • IN_CREATE : un fichier a été créé dans le répertoire surveillé.

Dans le mécanisme standard de inotify, il n’y a pas de notion de récursivité : un événement dans /home/georgette/.ssh ne sera pas remonté par un watch descriptor surveillant /home ; cependant, les outils implémentant inotify gèrent en général eux‐mêmes cette récursivité (en positionnant des watch descriptors dans toute l’arborescence, et en ajoutant dynamiquement des watch descriptors à chaque fois qu’un événement IN_CREATE survient).

Incron : mieux que des tâches planifiées, des tâches instantanées

 Principe

Les administrateurs de systèmes GNU/Linux connaissent tous le gestionnaire de tâche planifié cron, qui permet de lancer des tâches selon une planification cyclique (par exemple tous les dimanches à 14 h) définie dans une crontab, c’est‐à‐dire un fichier indiquant la tâche à exécuter et l’heure à laquelle elle doit être exécutée. Le logiciel incron reprend ce principe, mais, plutôt que de se baser sur des événements temporels, il se base sur des événements inotify.

 Installation

Le logiciel incron est empaqueté par la plupart des distributions, il suffit donc de l’installer à l’aide de votre gestionnaire de paquets préféré :

# pour Debian, Ubuntu, etc.
$ apt-get install incron

# pour Red Hat, CentOS etc.
$ yum install incron

Une fois installé, il faut insérer les utilisateurs autorisés à utiliser incron dans le fichier /etc/incron.allow :

$ cat /etc/incron.allow
httpadm
nagios
georgette

Utilisation

Pour créer une tâche dans la « incrontab », lancer la commande incrontab -e, et y déclarer l’événement et la commande associée. Par exemple, on peut demander à lancer automatiquement la commande postalias lorsque le fichier /etc/aliases est modifié :

/etc/aliases IN_MODIFY postalias

Note : incron fait partie des logiciels qui n’implémentent pas la récursivité.

lsyncd : vers un système de fichiers distribué

Principe

Mettre en place un système de fichiers distribué peut s’avérer compliqué, puisque cela implique en général une phase de migration des données existantes dans un nouveau système de fichiers qu’il faut avoir installé sur de nouveaux disques, voire de nouveaux serveurs. Le logiciel lsyncd permet de simuler un système de fichiers distribué en synchronisant simplement les fichiers d’une arborescence, en utilisant rsync. L’avantage de lsyncd est que la synchronisation est faite à chaque modification, et dès que celle‐ci intervient : cela simule presque parfaitement un système de fichiers distribué synchrone

Mise en place

lsyncd est empaqueté pour la plupart des distributions GNU/Linux, il suffit donc de l’installer via votre gestionnaire de paquets habituel. La configuration se fait à l’aide de scripts en langage Lua. Si vous n’êtes pas habitué à utiliser ce langage, vous pouvez suivre les exemples donnés dans la documentation. Ici, on va synchroniser /var/www/mon_site :

# cat /etc/lsyncd.conf.lua
    -- configuration de lsyncd
    settings{
        statusFile = "/tmp/lsyncd.stat",
        statusInterval = 1,
        insist = 1,
        inotifyMode = "CloseWrite or Modify",
    }
    -- liste des serveurs vers lesquels synchroniser
    targetlist = {
        "web01::mon_site", 
        "web02::mon_site", 
        "web03::mon_site" 
    }
    -- configuration de la synchronisation
    for _, server in ipairs(targetlist) do
        sync{ default.rsync,
            source="/var/www/mon_site",
            target=server
        }
    end

Pour que la synchronisation fonctionne, il faudra bien évidemment configurer rsync sur les serveurs web01, web02 et web03 pour que la destination mon_site pointe vers /var/www/mon_site.

 iwatch : ceci n’est pas une montre

Le logiciel iwatch permet de déclencher une action suite à un événement inotify. Il s’agit d’un logiciel destiné à l’origine à la surveillance, on s’en sert donc habituellement pour envoyer un courriel lorsqu’un fichier est modifié. Par exemple, pour prévenir Georgette de chaque modification de /etc/shadow :

iwatch -m georgette@example.com /etc/shadow

Contrairement à incron, iwatch gère la récursivité (avec l’option -r) et les exclusions (avec l’option -x pour un chemin, et -X pour une expression rationnelle), par exemple pour lancer l’antivirus pour chaque modification dans /var/www/upload (ou un de ses sous‐répertoires) sauf des fichiers .png :

iwatch -r -X '\.png$' -c "clamscan %f" /var/www/upload

Ici, %f pointe vers le fichier ayant déclenché l’événement.

inotify-tools : mettez de l’inotify dans votre ligne de commande

Les inotify-tools permettent de faire des appels inotify directement en ligne de commande, quel que soit le shell utilisé.

inotifywait

La première commande fournie est inotifywait, qui permet d’attendre un événement avant de continuer une exécution, par exemple pour éviter qu’une commande ayant un fichier en prérequis tombe en erreur :

inotifywait -e close_write /var/run/jboss.pid && supervision_jboss.sh

L’option -t (timeout) permet de mettre en place un délai d’expiration en secondes pour, par exemple, sortir en erreur si un événement est trop long à arriver :

sauvegarde.sh & ; inotifywait -e close_write -t 10000 rapport_sauvegarde || killall sauvegarde.sh

inotifywatch

La commande inotifywatch permet de faire un rapport d’activité des événements concernant les répertoires surveillés :

$ inotifywatch /var/cache/apt/archives &
[1] 18607
root@kamoulix:~# Establishing watches...
Finished establishing watches, now collecting statistics.

root@kamoulix:~# apt-get autoclean
root@kamoulix:~# kill %1
total  access  close_write  close_nowrite  open  delete  filename
1919   7       1            2              3     1906    /var/cache/apt/archives/

Par défaut, inotifywatch s’arrêtera après avoir un reçu un signal d’interruption. On peut aussi le faire tourner juste pour un certain nombre de secondes avec l'option -t, par exemple pour voir l’activité du répertoire home de l’utilisateur georgette pendant une minute :

$ inotifywatch -r /home/georgette/ -t 20
Establishing watches...
Finished establishing watches, now collecting statistics.
total  access  modify  close_write  close_nowrite  open  moved_from  moved_to  create  filename
16     3       3       2            0              2     2           2         2       /home/georgette/.mozilla/firefox/e3lq4lm3.default/
13     11      0       0            1              1     0           0         0       /home/georgette/.cache/myapp/mycache/

 Codez avec inotify

Les principaux langages de programmation proposent une bibliothèque pour travailler avec inotify, en voici une liste non exhaustive :

Aller plus loin

  • # Éditeurs de texte

    Posté par  (site web personnel) . Évalué à 10.

    Bonne dépêche !

    Attention cependant aux éditeurs de fichiers qui le plus souvent n'éditent pas un fichier sur place mais l'écrase (suppression puis réécriture). Du coup surveiller un événement IN_MODIFY ne servira a rien.

    Il existe deux catégories de gens : ceux qui divisent les gens en deux catégories et les autres.

    • [^] # Re: Éditeurs de texte

      Posté par  . Évalué à 3.

      Le plus pertinent, dans ce cas, est de surveiller IN_CLOSE_WRITE / IN_MOVED_FROM (suivant la façon de procéder de l'éditeur) sur le fichier en question, ce qui permet de ne déclencher l'action qu'une fois le fichier stable, et non pas à chaque write().

  • # Surveillance de la suppression de fichiers

    Posté par  . Évalué à 7.

    Bonsoir !

    Cette dépêche est intéressante. Merci. Et elle tombe bien : j'ai découvert récemment cette famille de commande car, suite à la disparition mystérieuse de fichiers partagés sur mon serveur (dans un cadre professionnel) je souhaitais surveiller (tout en le faisant savoir) d'éventuelles futures disparitions massives et suspectes… mais je n'ai pas su comment faire pour récupérer l'utilisateur déclencheur de l'événement. En fait je n'ai pas réussi à voir dans les doc si c'était possible… et comme j'ai pu mettre cette surveillance en place au niveau de samba avec le module "full audit", je n'ai pas approfondi plus que cela. Mais cela m'intéresserais de savoir…

  • # Et systemd ?

    Posté par  (site web personnel) . Évalué à 10.

    À noter aussi que les unités systemd de type path utilisent inotify. On peut donc utiliser systemd en lieu et place d'incron. Pour l'exemple donné ici, demander à lancer automatiquement la commande postalias lorsque /etc/aliases est modifié (totalement non testé mais c'est l'idée) :

    le fichier /etc/systemd/system/aliases.path

    [Path]
    PathModified=/etc/aliases
    [Install]
    WantedBy=multi-user.target

    le fichier /etc/systemd/systemd/aliases.service

    [Service]
    ExecStart=/usr/sbin/postalias

    Il est aussi possible d'utiliser ces fonctionnalités sans accès root en mettant les unités dans le dossier $XDG_CONFIG_HOME/systemd/user/*.

    • [^] # Re: Et systemd ?

      Posté par  (site web personnel) . Évalué à 3.

      C'est amusant, car je voulais justement voir si le souci qu'on trouve sur upstart ( https://rachelbythebay.com/w/2014/11/24/touch/ ) serait géré par systemd. J'ai rien vu sur le fait d'avoir une gestion à ce niveau, mais si ça crashe pas, ça veut rien dire.

    • [^] # Re: Et systemd ?

      Posté par  (site web personnel) . Évalué à 3.

      Bonsoir,

      sincèrement, je trouve que :

      /etc/aliases IN_MODIFY postalias

      est largement plus simple que deux fichiers pour systemd avec des syntaxes obscures:

      le fichier /etc/systemd/system/aliases.path

      [Path]
      PathModified=/etc/aliases
      [Install]
      WantedBy=multi-user.target
      

      le fichier /etc/systemd/systemd/aliases.service

      [Service]
      ExecStart=/usr/sbin/postalias
      

      Pourquoi bloquer la publicité et les traqueurs : https://greboca.com/Pourquoi-bloquer-la-publicite-et-les-traqueurs.html

      • [^] # Re: Et systemd ?

        Posté par  (site web personnel) . Évalué à 4.

        Bonsoir,

        c'est une affaire de goûts, mais la syntaxe de systemd me semble au contraire plus explicite (dans la configuration incron, les champs de sont pas explicites, il faut connaître la syntaxe du fichier pour le comprendre).

        Elle n'est en tous cas pas plus obscure que celle d'incron (puisque les deux sont très bien documentées).

        De plus systemd permet un peu plus de choses (démarrage conditionnel, dépendances, cgroups, etc).

  • # Utilisation transparente avec compass par exemple

    Posté par  (site web personnel) . Évalué à 6.

    Pour ceux qui font du développement web et qui utilisent sass, alors ils utilisent très certainement compass pour compiler leurs fichiers sass à la volée (après chaque modification) vers les fichiers cibles.
    En coulisse compass utilise inotify.

    p.s:
    - sass : http://sass-lang.com/
    - compass : http://compass-style.org/

  • # Quelques articles

    Posté par  . Évalué à 9.

    Pour ceux qui sont intéressés par les notifications, il y a l'excellente série d'articles de lwn :
    http://lwn.net/Articles/604686/
    http://lwn.net/Articles/605128/

  • # Kill init by touching a bunch of files

    Posté par  (site web personnel) . Évalué à 5.

    Coïncidence (ou non ?!), aujourd'hui sur HackerNews il y a un article sur un d'une bibliothèque système (libnih, dans Ubuntu UpStart) qui plante le système en kernel panic à cause d'une mauvaise utilisation d'inotify ! (quand plus de$(sysctl fs.inotify.max_queued_events) fichiers (16384) sont touchés à la fois !

    • [^] # Re: Kill init by touching a bunch of files

      Posté par  . Évalué à 8.

      Alors ce n'est pas touché en même temps, mais si on traite les événements trop lentement par rapport à leur vitesse d'arrivé. Immaginons par exemple qu'on utilise un script shell à base d'inotifywait qui traite tous les nouveaux fichiers (disons les nouveaux fichiers et ceux déplacés) et que le traitement prend 1s. Si tu déplace beaucoup de fichiers dans ce dossier (par exemple une restauration d'archive ou la création d'un clone de dépôt git/hg, tu va voir ta file d'attente exploser.

      La solution c'est :

      • de ne jamais traiter les événements dans le même thread que la boucle d'événements inotify
      • de traiter l'événement spécial qui indique que des événements ont étaient dropé de la queue

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Cas pratique

    Posté par  (site web personnel, Mastodon) . Évalué à 5.

    Merci pour la dépêche, très instructive.

    Je me sers de temps à autre d'inotifywait couplé à D-Bus pour avoir un aperçu en temps réél. J'ai d'ailleurs expliqué récemment sur mon blog comment le faire pour éditer une XEP.

    C'est quand même super pratique ces outils…

  • # Race conditions

    Posté par  . Évalué à 5.

    en positionnant des watch descriptors dans toute l'arborescence, et en ajoutant dynamiquement des watch descriptors à chaque fois qu'un événement IN_CREATE survient en positionnant des watch descriptors dans toute l'arborescence, et en ajoutant dynamiquement des watch descriptors à chaque fois qu'un événement IN_CREATE survient

    C'est pas un peu sujet à des bonnes grosses race conditions ça ?

    • [^] # Re: Race conditions

      Posté par  . Évalué à 3.

      Je ne vois pas le cas d'usage dans lequel ça pourrait arriver, il ne faut pas avoir peur du récursif.

      Membre de l'april, et vous ? https://april.org/adherer -- Infini, l'internet libre et non commercial : https://infini.fr

      • [^] # Re: Race conditions

        Posté par  . Évalué à 3.

        Tranquillou, tu mets un script qui crée un sous-dossier 'toto' dans qu'un dossier est créé dans une arborescence. Et là, tu as dossier/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto/toto

        ⚓ À g'Auch TOUTE! http://afdgauch.online.fr

        • [^] # Re: Race conditions

          Posté par  . Évalué à 6.

          Je ne vois pas le rapport avec une race condition

          Tout au plus on pourrait avoir une récursion infinie, sauf qu'en fait non, parce que la profondeur de répertoire n'est pas illimitée (la longueur totale de la chaîne de caractère d'un path est limitée en dur par un #define du noyau, dont le nom et la valeur m'échappent)

          Donc en fait c'est ni une race condition ni une récursion infinie, c'est juste un truc con qu'on peut faire si on se pisse sur les doigts en utilisant inotify, ça reste moins dangereux qu'un kilo de plutonium mais ne reproduisez pas cette expérience chez vous®, inotify ça coupe presqu'autant qu'un couteau de cuisine, vous aurez été prévenus…

          • [^] # Re: Race conditions

            Posté par  (site web personnel) . Évalué à 4.

            Le fameux PATH_MAX cher aux porteurs GNU/Hurd !

            include/uapi/linux/limits.h:#define PATH_MAX 4096 /* # chars in a path name including nul */

            Debian Consultant @ DEBAMAX

          • [^] # Re: Race conditions

            Posté par  . Évalué à 5.

            Tout au plus on pourrait avoir une récursion infinie, sauf qu'en fait non, parce que la profondeur de répertoire n'est pas illimitée (la longueur totale de la chaîne de caractère d'un path est limitée en dur par un #define du noyau, dont le nom et la valeur m'échappent)

            Il n'y a pas que la valeur du define qui t'échappe…

                #!/bin/bash
            
                u="toto long"
                while true; do
                        mkdir $u
                        cd ./$u
                        pwd |wc -c
                        sleep 1
                done
            


            6984
            6989
            6994
            6999

            Le maxpath est relatif et ne limite pas la profondeur de l'arbo …

    • [^] # Re: Race conditions

      Posté par  . Évalué à 1.

      Ce qui est bizarre avec inotify, c'est que le l'ajout de répertoire fonctionne parfaitement, mais dès que vous en déplacez un hors du scope (répertoires surveillés) de inotify, et que plus tard vous le re-déplacez dans le scope, il se passe des choses bizarres:

      • L'ancien watch nommé nodurépertoire devient nodurépertoire-unknown-path
      • Un nouveau watch est automatiquement créé. Bref il faut retirer les watch à la main.

      ex:
      répertoire surveillé: /tmp/inotify/

      # mkdir /tmp/inotify/aze
      Event IN_CREATE|IN_ISDIR on /tmp/inotify/aze
      Event IN_OPEN|IN_ISDIR on /tmp/inotify/aze
      Event IN_OPEN|IN_ISDIR on /tmp/inotify/aze
      Event IN_CLOSE_NOWRITE|IN_ISDIR on /tmp/inotify/aze
      Event IN_CLOSE_NOWRITE|IN_ISDIR on /tmp/inotify/aze
      # touch /tmp/inotify/aze/k
      Event IN_CREATE on /tmp/inotify/aze/k
      Event IN_OPEN on /tmp/inotify/aze/k
      Event IN_ATTRIB on /tmp/inotify/aze/k
      Event IN_CLOSE_WRITE on /tmp/inotify/aze/k
      # mv /tmp/inotify/aze /tmp/
      Event IN_MOVED_FROM|IN_ISDIR on /tmp/inotify/aze
      [2014-11-25 08:59:08,714 pyinotify ERROR] The pathname '/tmp/inotify/aze' of this watch <Watch wd=3 path=/tmp/inotify/aze mask=4095 proc_fun=None auto_add=True exclude_filter=<function <lambda> at 0x9dfd454> dir=True > has probably changed and couldn't be updated, so it cannot be trusted anymore. To fix this error move directories/files only between watched parents directories, in this case e.g. put a watch on '/tmp/inotify'.
      Event IN_MOVE_SELF on /tmp/inotify/aze-unknown-path
      # mv /tmp/aze /tmp/inotify/
      Event IN_MOVED_TO|IN_ISDIR on /tmp/inotify/aze
      [2014-11-25 09:00:15,900 pyinotify ERROR] The pathname '/tmp/inotify/aze' of this watch <Watch wd=3 path=/tmp/inotify/aze mask=4095 proc_fun=None auto_add=True exclude_filter=<function <lambda> at 0x9dfd454> dir=True > has probably changed and couldn't be updated, so it cannot be trusted anymore. To fix this error move directories/files only between watched parents directories, in this case e.g. put a watch on '/tmp/inotify'.
      Event IN_MOVE_SELF on /tmp/inotify/aze-unknown-path
      Event IN_OPEN|IN_ISDIR on /tmp/inotify/aze
      Event IN_OPEN|IN_ISDIR on /tmp/inotify/aze-unknown-path
      Event IN_CLOSE_NOWRITE|IN_ISDIR on /tmp/inotify/aze
      Event IN_CLOSE_NOWRITE|IN_ISDIR on /tmp/inotify/aze-unknown-path
      
      • [^] # Re: Race conditions

        Posté par  (site web personnel) . Évalué à 2. Dernière modification le 25 novembre 2014 à 15:55.

        Ça semble plus être un problème du coté de pyinotify qu'une bizarrerie de l'API :

        $ inotifywait -rm /tmp/inotify/
        [...]
        
        $ mkdir /tmp/inotify/aze
        /tmp/inotify/ CREATE,ISDIR aze
        /tmp/inotify/ OPEN,ISDIR aze
        /tmp/inotify/ CLOSE_NOWRITE,CLOSE,ISDIR aze
        
        $ touch /tmp/inotify/aze/k
        /tmp/inotify/aze/ CREATE k
        /tmp/inotify/aze/ OPEN k
        /tmp/inotify/aze/ ATTRIB k
        /tmp/inotify/aze/ CLOSE_WRITE,CLOSE k
        
        $ mv /tmp/inotify/aze /tmp/
        /tmp/inotify/ MOVED_FROM,ISDIR aze
        /tmp/inotify/aze/ MOVE_SELF 
        
        $ mv /tmp/aze /tmp/inotify/
        /tmp/inotify/ MOVED_TO,ISDIR aze
        /tmp/inotify/ OPEN,ISDIR aze
        /tmp/inotify/ CLOSE_NOWRITE,CLOSE,ISDIR aze
        

        (inotifywait 3.14, Kernel 3.9.10)

        Pas de plainte lorsque le répertoire s'en va (le parent autant que le répertoire lui-même "voient" l'événement) et pas de problème particulier lorsque le répertoire revient.

        D'ailleurs inotifywait se débrouille pour ajouter à nouveau des watches dans ce répertoire (parce qu’il est en mode récursif, j'imagine) :

        $ ls -l /proc/$(pidof inotifywait)/fd  | grep anon_inode:inotify
        lr-x------ 1 xfennec xfennec 64 25 nov.  15:37 3 -> anon_inode:inotify
        
        $ cat /proc/$(pidof inotifywait)/fdinfo/3 | grep inotify
        inotify wd:4 ino:162801 sdev:fd00001 mask:800afff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:01281600a35a90fa
        inotify wd:2 ino:162195 sdev:fd00001 mask:800afff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:952116009d5a90fa
        
        ls -lai /tmp/inotify/
        1450389 drwxrwxr-x   4 xfennec xfennec  4096 25 nov.  15:48 .
        1438977 drwxrwxrwt. 34 root    root    20480 25 nov.  15:47 ..
        1452033 drwxrwxr-x   2 xfennec xfennec  4096 25 nov.  15:35 aze
        

        0x162801 = 1452033 (/tmp/inotify/aze)
        0x162195 = 1450389 (/tmp/inotify)

  • # Procès du pommier

    Posté par  . Évalué à 4.

    Z'êtes fous de nommer ainsi ce composant : non seulement il y a une faute d'orthographe - iNotify ! - mais vous allez vous prendre un procès de la Pomme, c'est leur nom breveté de la puce qui va nous gratter le cou pour nous rappeller nos RDV….

    ⚓ À g'Auch TOUTE! http://afdgauch.online.fr

  • # Chouette article, merci !

    Posté par  . Évalué à 5.

    Merci !
    Nous utilisons incron pour lancer des traitements sur des fichiers depuis 2 ans, et ça fait un serveur de traitement très simple :-)

    Sinon, j'attends avec impatience un article au sujet des "suavegardes" :-)

  • # Utilisation par transmission?

    Posté par  (site web personnel) . Évalué à 4.

    Est-ce que ça ne pourrait pas être utilisé par transmission pour qu’on puisse renommer/déplacer/supprimer les fichiers téléchargés en torrent sans problème et sans cesser de seed?

    Est-ce qu’il y a d’autres clients torrent qui le font?

    • [^] # Re: Utilisation par transmission?

      Posté par  . Évalué à 2.

      Je sais pas si ça répond mais il me semble que dans Transmission on choisit la destination finale du fichier quand on charge le .torrent et on peut spécifier un emplacement par défaut différent pour les fichiers en cours de téléchargement.

      Une fois fini, le fichier est déplacé par Transmission du répertoire temporaire vers l'emplacement choisi et continue d'être partagé.

      • [^] # Re: Utilisation par transmission?

        Posté par  (site web personnel) . Évalué à 3.

        Non, ça ça permet de placer le fichier où on veut, mais pas de le renommer par exemple. Ou de changer l’organisation de l’arborescence des fichiers du torrent.
        Vraiment, si transmission surveillait les changements fichiers la vie serait plus belle.

  • # exploitation

    Posté par  . Évalué à 1.

    Bonjour les pti zamis,

    Personnellement, j'ai toujours beaucoup de mal avec cette techno, car j'ai un problème d'exploitabilité. Notamment:

    • comment obtenir la liste de ce qui est surveillé par inotify?
    • est-ce que cela se monitore? ex: est-ce qu'il y a un démon qui surveille ou est-ce que c'est le noyau qui gère tout?
    • quel est le degré de maturité? quel est le risque de manquer des fichiers?

    Voila le genre de question qui rend inotify obscure…

    • [^] # Re: exploitation

      Posté par  . Évalué à 4.

      est-ce qu'il y a un démon qui surveille ou est-ce que c'est le noyau qui gère tout?

      C'est le noyau qui gère tout. Tu peut par dessus construire un deamon comme tu le souhaite.

      quel est le degré de maturité?

      De ce que j'en sais elle est bonne. C'est un API qui est pas mal utilisée et qui n'a pas subit d'énormes changement depuis son inclusion.

      quel est le risque de manquer des fichiers?

      Aucun si tu suis les bonnes pratiques, c'est-à-dire, comme je le dis plus haut d'avoir un thread qui ne s'occupe que d'intégrer les évènements au reste de ton système et de prendre en compte l'évènement qui indique que la file d'évènements est pleine.

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: exploitation

        Posté par  . Évalué à 2.

        En fait il me manque le principal :

        comment obtenir la liste de ce qui est surveillé par inotify?

    • [^] # Re: exploitation

      Posté par  (site web personnel) . Évalué à 10. Dernière modification le 25 novembre 2014 à 16:10.

      Pour la liste de ce qui est « surveillé par inotify », la piste la plus intéressante est probablement /proc (une autre étant lsof)

      Les processus qui font appel à l'API montre un fd qui pointe vers anon_inode:inotify. Exemple : find /proc/*/fd/* -lname 'anon_inode:inotify'. C'est une « instance » inotify (inotify_init()).

      Il suffit alors d'aller voir le fdinfo correspondant pour voir quels inodes sont surveillées :

      $ cat /proc/2006/fdinfo/13
      pos:    0
      flags:  02000000
      inotify wd:1 ino:60334 sdev:fd00002 mask:800afc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:340306004ca43e19
      

      Ici c'est l'inode 0x60334 (/home/xfennec/.kde/share/apps/korganizer/std.ics, c'est un « watch » inotify). Si c'est un répertoire, c'est l'ensemble de son contenu « direct » (de niveau 1, quoi) qui est surveillé.

  • # Repwatcher - surveillance accès fichiers

    Posté par  . Évalué à 8.

    Salut à tous,

    voilà plusieurs années que je développe une application (en OCaml) qui surveille les accès à des fichiers dans des dossiers surveillés puis remonte les informations collectées.

    A l'origine (2007-2008 je crois), le but était d'avoir un log lorsque des personnes téléchargeaient des fichiers chez moi par SSH. J'avais donc besoin d'avoir une date de début et de fin, le path, le nom du fichier et le nom du téléchargeur.
    En effet, je voyais de la bande passante partir la nuit mais sans savoir ce qu'il s'était vraiment passé.
    Aujourd'hui, cela ne se limite pas à SSH.

    Il y a plusieurs canaux (au choix) pour la remontée d'informations:
    - enregistrement dans une base de données (MySQL ou PostgreSQL)
    - envoi d'un mail (instantané ou bufferisé)
    - envoi d'une notification local (popup à l'écran) ou distante (authentification mutuelle TLS entre les clients et le serveur puis la popup par appel dbus)

    L'application vérifie également la progression de lecture du fichier ouvert en vérifiant son offset.
    On peut ainsi en déduire où la vitesse de lecture/écriture.

    Petit retour d'expérience sur inotify:
    - Inotify retourne peu d'informations à l'application qui lit la socket. Du coup, c'est à l'application de maintenir tout une liste d'informations.
    Comme dit précédemment, si on met un dossier en surveillance, ce n'est pas récursif. Il faut donc soi-même faire le parcours en profondeur et gérer la filiation des dossiers.
    Si un dossier est déplacé, cela revient à supprimer et tout refaire.

    • Pour simplifier, lors de l'accès à un fichier, inotify vous dit "ça s'est passé dans le dossier watch id 42 pour le fichier «bidule», celui avec le watch id 42". Vous n'avez pas le chemin complet du dossier, et s'il y a plusieurs accès différents au même fichier, c'est à vous de vous débrouiller pour savoir que l'event CLOSE sur le fichier est correspond à tel ou tel évènement d'ouverture.

    https://github.com/gbe/repwatcher

    • [^] # Re: Repwatcher - surveillance accès fichiers

      Posté par  . Évalué à 3.

      A noter aussi l'existence de Watchman: https://facebook.github.io/watchman/

      Facebook l'utilise avec un Mercurial customise avec des plugins pour faire des checkout de leur frontend qui contiendrait 2.5 millions de fichiers au bas mot.

    • [^] # Re: Repwatcher - surveillance accès fichiers

      Posté par  . Évalué à 1.

      mince, je pensais que tu avais une meilleure méthode qu'inotify….. Je me voyais déjà en faire un binding pour nodejs… Mais comme je viens de lire le code source, je me rends compte qu'en fait tu utilises inotify itself à l'intérieur. Donc je suis un peu déçu après la lecture de votre commentaire.

      Ceci dit, j'ai trouvé que les commentaires et la syntaxe globale du main était vraiment belle et agréable à lire. Je ne sais pas si c'est standard, mais j'aimes bien..

  • # Pas toujours évident...

    Posté par  . Évalué à 3.

    Bonjour,

    J'ai testé récemment incron pour faire un outil de transformation automatique d'un fichier audio dans un format particulier : le principe est que tout fichier placé dans un répertoire (par exemple traduction_mp3/source/) soit transformé (avec ffmpeg) dans ce format audio (et placé dans traduction_mp3/resultat/). Sur le papier c'est assez simple, mais j'ai eu quelques soucis d'implémentation :

    • le démon incrond qui joue avec les commentaires (voir https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=563700), c'est assez pénible…

    • le choix des bons événements INOTIFY à suivre n'est pas évident… J'ai notamment eu du mal pour être sûr que lorsqu'on copie un gros fichier dans le répertoire, le script ne commence pas la traduction avant que le fichier soit complètement copié… J'ai fini par attendre que la date de modification du fichier soit quelques secondes après l'heure courante pour décider que je pouvais les traiter…

  • # Pour nodejs

    Posté par  . Évalué à 1.

    Tant qu'on y est !
    http://nodejs.org/api/fs.html#fs_fs_watchfile_filename_options_listener

    A noter qu'on peut être indépendant de la plateforme dans ce cas ci. M'enfin je crains que le niveau de qualité ne soit pas tout à fait le même.

    Ceci dit, je ne comprends pas pourquoi cette interface n'est pas refondu.
    Deux raisons à cela, ce n'est pas récursif, et lorsque l'on s'abonne à beaucoup de fichiers, il y à des limites.
    Alors, je ne sais pas comment tout cela fonctionne en interne, et pour le coup, je m'éviterais de pré juger.
    Par contre je me doit de demander pourquoi on ne pourrait pas avoir un simple événement propager à tous les changements du système de fichier, avec uniquement deux arguments d'appel, le chemin d'accès, le type d'opération.

    Cela ne couvrira pas tous les cas que dest /http://linuxfr.org/users/dest / à dû rencontrer, mais cela répondra déjà à tellement de cas, de manière tellement efficace……… 'fin voilà, je ne sais pas si on peut expliquer cela sans y perdre trop de temps, mais je pose la question.

    • [^] # Re: Pour nodejs

      Posté par  (site web personnel) . Évalué à 1.

      A mon avis, c'est parce que ce n'est pas au Kernel de gérer ça.

      La récursivité, c'est quelque chose qu'il est possible d'implémenter au niveau de l'espace utilisateur. Du coup, peut-être manque-t-il une API un peu plus haut niveau pour répondre à ces besoins manifestement récurrents ?

    • [^] # Re: Pour nodejs

      Posté par  . Évalué à 3.

      A l'oppose, quelle serait la scalabilité d'une solution récursive?
      Quel serait l'impact sur le noyau?

      Ils ont peut-être préféré privilégier la stabilité du noyau.

      • [^] # Re: Pour nodejs

        Posté par  . Évalué à 2. Dernière modification le 27 novembre 2014 à 11:44.

        Hmm je ne sais pas, mais si je pouvais m'abonner à un événement et qu'il me renvoie un chemin d'accès, alors la récursivité je la gère tout seul, sans problème de performances.

        Il suffira de faire un /mon_dossier/modifie/.match(/\/mon_dossier\//) pour être récursif à mon_dossier.
        Et je n'ai pas besoin de souscrire à 15 000 écouteurs. Et je peux faire du throttling pour fusionner les appels multiples séparés de cours instants.

        Après je me dit que l'implémentation actuel a ces raisons, j'appels à les dépasser : )

        • [^] # Re: Pour nodejs

          Posté par  . Évalué à 4.

          Pour connaître la raison de la non-récursivité, il suffit de demander à la source : http://www.quora.com/Inotify-monitoring-of-directories-is-not-recursive-Is-there-any-specific-reason-for-this-design-in-Linux-kernel

          Membre de l'april, et vous ? https://april.org/adherer -- Infini, l'internet libre et non commercial : https://infini.fr

          • [^] # Re: Pour nodejs

            Posté par  . Évalué à 2. Dernière modification le 27 novembre 2014 à 12:09.

            Ok il explique que le faire de manière bête et méchante, c'est lent et pas terrible.

            M'enfin, dans mon idée, on ne poserait pas un watcher sur un dossier, on poserait un watcher sur un système de fichier entier, à lui de nous prévenir à chaque écriture. Avec plus ou moins de granularité.

            Après je lis des commentaires comme celui ci

            Given complete information about the initial state of a watched directory tree, and given a list of all of the inotify events generated by a set of file operations on that tree, it is possible to accurately compute the final state of the tree.

            Et franchement je m'interroges… Pourquoi resté fixer sur cette idée de poser un watcher sur un dossier ou un fichier et tenter de gérer des cas d'userspace dans la lib ?
            Dans son exemple, il me paraît évident que le problème n'est pas soluble, mais bon, j'ai surement loupé une étape.

            Mais merci tout de même pour le lien !

  • # Incron

    Posté par  . Évalué à 2.

    A noter que le projet incron est a l'abandon, cf http://inotify.aiken.cz/?section=common&page=news&lang=en.

    Les autres projets (inotify-tools p.ex) ne sont pas bien plus actifs… mais lsyncd est maintenu!

    Au passage, sous BSD il existe un équivalent avec le mécanisme kqueue (ptet avec un peu moins de features) et une couche de compat avec l'API d'inotify existe, donc on peut tester incron/inotify-tools/lsyncd sous BSD. En tout cas, ils se portent sur OpenBSD.

    • [^] # Re: Incron

      Posté par  (site web personnel, Mastodon) . Évalué à 1.

      Si j'ai bien compris le message, ce n'est pas qu'incron qui est abandonné, mais tout le projet inotify… Quelqu'un pour confirmer ?

      • [^] # Re: Incron

        Posté par  (site web personnel) . Évalué à 5.

        Non, c'est incron et inotify-cxx. inotify tout court, c'est une API du noyau (des appels systèmes) qui n'est pas développée par la personne qui tient le site dont il est question.

    • [^] # Re: Incron

      Posté par  (site web personnel) . Évalué à 2.

      il existe un équivalent avec le mécanisme kqueue

      Absolument pas. Kqueue monitore un descripteur de fichier là ou inotify monitore un noeud du vfs. Un autre mécanisme pour avoir quelque chose d'équivalent peut être d'utiliser audit qui travaille lui plutôt au niveau des appels systèmes.

      Je ne sais pas comment c'est implémenté en détail au niveau du vfs dans linux mais ce qui est remarquable d'après ce que j'ai compris c'est que ce n'est pas dépendant du système de fichier sous jacent. Sous freebsd‚ que je connais un peu, je ne vois pas trop comment un tel mécanisme serait possible sans une modification profonde du vfs.

      Bref il existe sous BSD des mécanismes qui peuvent offrir une fonctionnalité équivalente comme tu le signalais mais ce n'est absolument pas la même chose au niveau du fonctionnement interne et en particulier de la legereté du processus de supervision des fichiers. Du coup au niveau utilisateur on est plus proche de dnotify avec tous les problèmes que inotify a résolu

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.