inotify para monitorar diretórios

O que é o inotify?

O inotify é um subsistema que provê eventos de notificação provenientes do sistema de arquivos – notifica modificações nos arquivos. Foi escrito por John McCutchan com ajuda de Robert Love e depois Amy Griffis, para substituir o sistema antigo, dnotify – que por sua vez executava a mesma tarefa, de maneira diferente.

Foi incluído oficialmente no kernel 2.6.13, embora seja possível usá-lo em versões anteriores aplicando um patch. É basicamente uma extensão do sistema arquivos que visa notificar modificações e relatá-las para aplicações.

É normalmente usado por sistemas de busca no desktop, onde é possível reindexar a base de informações sem a necessidade de escanear o sistema de arquivos em intervalo pré-determinado, que seria ineficiente. Quando a aplicação pode ser avisada que um arquivo foi modificado, diretamente pelo kernel – ao invés de escanear cada arquivo – esses sistemas passam a consumir muito menos recursos e podem manter sua base atualizada, fornecendo respostas eficientes mesmo após alguns segundos da modificação.

Também pode ser usado para recarregar arquivos de configuração automaticamente, monitorar modificações em arquivos de log, backup, sincronização, e upload.

O texto acima foi traduzido do Wikipédia.

Inotify no python

A implementação original é em C, através de system calls. Porém, há um binding dessas chamadas para python, que permite usar o inotify no python.

Como o pyinotify não é parte oficial do python, é necessário instalá-lo no sistema antes de usar. Se você usa Debian ou Ubuntu, basta executar sudo apt-get install python-pyinotify.

O exemplo abaixo permite monitorar diretórios para encontrar arquivos novos ou modificados, monitorando-os usando o evento IN_CLOSE_WRITE. Este evento notifica a aplicação quando um arquivo foi fechado, e teve escrita. Significa que se um arquivo foi apenas lido por outro programa, não será notificado – nesse caso o evento é IN_CLOSE_NOWRITE. Esses eventos podem ser combinados usando IN_CLOSE_WRITE|IN_CLOSE_NOWRITE, mas não serão neste exemplo.

#!/usr/bin/env python
# coding: utf-8
# monitor.py 20071108 AF

import os, sys
from pyinotify import WatchManager, Notifier, ProcessEvent, EventsCodes

wm = WatchManager()

def Monitor():
    class close_event(ProcessEvent):
        def process_IN_CLOSE_WRITE(self, event):
            f = event.name and \
                os.path.join(event.path, event.name) or event.path
            print 'arquivo modificado: ' + f

    notifier = Notifier(wm, close_event())

    try:
        while 1:
            notifier.process_events()
            if notifier.check_events():
                notifier.read_events()
    except KeyboardInterrupt:
        notifier.stop()
        return

if __name__ == '__main__':
    try:
        dirlist = sys.argv[1:]
        if not len(dirlist): raise Exception
    except:
        print 'use: %s diretório' % sys.argv[0]
        sys.exit(1)

    for path in dirlist:
        print 'monitorando ' + path
        wm.add_watch(path, EventsCodes.IN_CLOSE_WRITE, rec=True)

    Monitor()

Basicamente, o processo é o seguinte:

  1. Cria-se um WatchManager;
  2. Adiciona-se um diretório por vez a ele usando wm.add_watch(), informando o evento a ser monitorado – por padrão, o monitoramento não é recursivo, mas pode-se ativar a recursividade usando rec=True;
  3. Cria-se um Notifier, informando qual é o WatchManager e qual é a classe com callbacks para os eventos selecionados – esta classe herda de uma ProcessEvent;
  4. Por fim, executa-se um loop infinito processa, checa e lê os eventos ocorridos no WatchManager, através do Notifier.

Em alguns casos esse loop infinito será indesejado, pois é nele que o processo fica executando. Caso seja necessário usar o pyinotify com algum toolkit gráfico que já possui seu próprio loop, pode-se usar um ThreadedNotifier ao invés do Notifier padrão.

Mais detalhes estão no Brief Tutorial do próprio pyinotify.

Anúncios


Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s