Monitorizar sistema de ficheiros com inotify

Existem muitas ocasiões onde é necessário monitorizar o nosso sistema de ficheiros, para saber o que se passa com algum ficheiro ou directoria. Existem muitas soluções, mas há algumas melhores que outras. Em Linux existe algo que se chama inotify.

A maioria dos sitemas Linux mais recentes já traz suporte para o inotify.

grep -i inotify /boot/config-$(uname -r)

CONFIG_INOTIFY=y

CONFIG_INOTIFY_USER=y

Como o inotify está no kernel, todos os programas desenvolvidos para Linux podem tirar partido dele sem usar nenhuma biblioteca especial.

Existe um conjunto de ferramentas, inotify-tools, que contém programas para usar esta funcionalidade fantástica do kernel. Esta ferramenta inclui aplicações como inotifywait e inotifywatch.

Primeiro, vamos instalar o inotify-tools. Em CentOS 6 não existe qualquer pacote nos repositorios oficiais, mas, estão disponiveis RPMs.

Em http://pkgs.repoforge.org/inotify-tools/, há pacotes para CentOS 6.

Se usarem o CentOS 6, o wget também não vem instalado e precisam de o instalar:

yum install wget

wget http://pkgs.repoforge.org/inotify-tools/inotify-tools-3.13-1.el6.rf.x86_64.rpm

rpm -ivh inotify-tools-3.13-1.el6.rf.x86_64.rpm

Para terem uma ideia do que o inotifywatch faz, experimentem:

Por exemplo, para monitorizar a nossa home

inotifywatch -r ~

Numa outra consola, abram o firefox, ou alguma outra aplicação.

Agora, na consola onde têm o inotifywatch aberto, interrompam a execução (Ctrl + C) e vejam as estatísticas que ele devolve:

total  attrib  close_write  close_nowrite  open  create  delete  filename

15     1       1            4              5     1       3       /root/

Com esta ferramenta, podem ver estatisticas .

Este comando vai verificar, recursivamente, todos os eventos que ocorrem na nossa home (neste caso). Podemos também refinar o nosso comando e apenas monitorizar os eventos que desejamos, usando a opção -e:

inotifywatch -e create, delete, delete_self -r ~

Desta forma, apenas quando ficheiros (ou directorias) forem criadas ou apagadas é que serão gerados eventos. Para saberem quais os eventos que podemos monitorizar:

inotifywatch --help

Events:

access file or directory contents were read

modify file or directory contents were written

attrib file or directory attributes changed

close_write file or directory closed, after being opened in writeable mode

close_nowrite file or directory closed, after being opened in read-only mode

close file or directory closed, regardless of read/write mode

open file or directory opened

moved_to file or directory moved to watched directory

moved_from file or directory moved from watched directory

move file or directory moved to or from watched directory

create file or directory created within watched directory

delete file or directory deleted within watched directory

delete_self file or directory was deleted

unmount file system containing file or directory unmounted

Com este comando, iremos ver (quando o terminarmos) o que aconteceu.

Existe um comando melhor, que permite visualizar em tempo real o que está a acontecer, ao contrário do inotifywatch. Esse comando chama-se inotifywait.

No entanto, o que desejamos é realmente que alguma acção seja realizada consoante um determinado evento seja detectado. Para isso, vamos usar o iwatch – http://iwatch.sourceforge.net/index.html
 
O iwatch faz isto tudo se algum evento acontecer na directoria ou ficheiro escolhidos. Depende de quatro módulos de PERL:
 
yum install perl-Event perl-Mail-Sendmail perl-XML-Simple perl-XML-SimpleObject perl-Linux-Inotify2
 
O iwatch pode-se executar de duas formas, ou como um daemon ou directamente na linha de comandos.
 

Linha de comandos

Para verem o que pode ser feito com o iwatch, vamos fazer um teste. Abram duas consolas.
Na primeira, executem o iwatch com o evento de criacao de ficheiros e onde envia um email a notificar:
 
./iwatch -r -e create,delete -m <nome>@<dominio> /tmp
e deixem estar.
 
Na outra consola, vão até à directoria /tmp e criem um ficheiro:
touch istoficheiro

Reparem que na consola com o iwatch a correr, ja apareceram eventos:
 
IN_CREATE /tmp/istoficheiro
[12/Jan/2011 19:35:44] * Send email to <nome>@<dominio>

Os eventos vistos pelo iwatch são vários. Estes foram apenas um exemplo.
Ao apagar um ficheiro (ou directoria):

IN_DELETE /tmp/istoficheiro
[12/Jan/2011 19:36:51] * /tmp/istoficheiro is deleted
[12/Jan/2011 19:36:51] * Send email to <nome>@<dominio>
 
Como podem ver, é simplesmente genial.
 
Agora, imaginem que não querem enviar um email, mas executar uma acção (duas consolas – numa executam o comando em baixo e na outra criam e removem ficheiros de tmp):
(primeira consola)
./iwatch -r -e create,delete -c "top" /tmp
 
(segunda consola)
touch ficheiro
 
(primeira consola)
[14/Jan/2011 14:30:33] IN_CREATE /tmp/ola
[14/Jan/2011 14:30:33] * /tmp/ola is deleted
[14/Jan/2011 14:30:33] * Command: top

 
Desta forma o iwatch executa o comando especificado quando algum dos eventos monitorizados acontecer.
 

Daemon mode

 
Este modo é talvez o melhor, pois não precisamos de indicar tudo na linha de comandos. O iwatch, neste modo, usa um ficheiro de configuração onde constam as directorias a monitorizar, os eventos e as acções.
 
O ficheiro chama-se iwatch.xml e a configuração é bastante simples. A sua sintaxe é xml. Em baixo está um exemplo.
 
<config charset="utf-8">
  <guard email="root@localhost" name="IWatch"/>
  <watchlist>
    <title>Public Website</title>
    <contactpoint email="webmaster@localhost" name="Web Master"/>
    <path type="single" syslog="on">/var/www/localhost/htdocs</path>
    <path type="single" syslog="off">/var/www/localhost/htdocs/About</path>
    <path type="recursive">/var/www/localhost/htdocs/Photos</path>
    <path type="single" events="default,access" alert="off" exec="(w;ps)|mail -s '%f is accessed at %{%H:%M:%S}d' root@localhost">/tmp/dir3</path>
    <path type="exception">/etc/mail/statistics</path>
  </watchlist>
</config>

Exemplo de configuração a funcionar:
Esta configuração monitoriza a directoria /var/www/html por ficheiros alterados, apagados ou criados. Quando algum desses eventos é gerado, executa o rsync para sincronizar a directoria com o servidor remoto.

<config charset="utf-8">
  <guard email="iwatch@localhost" name="IWatch"/>
  <watchlist>
    <title>Public Website</title>
    <contactpoint email="webmaster@localhost" name="webmaster"/>
    <path type="recursive" alert="off" events="create,delete,modify" exec="rsync -avz --delete -e ssh /var/www/html/ root@otherHost:/var/www/html">/var/www/html</path>
  </watchlist>
</config>

Podemos especificar várias directorias a monitorizar, onde podemos monitorizar apenas a directoria ou recursivamente todas as que se encontrem por baixo dela (type). 
Para cada directoria podemos especificar se queremos ser notificados por email (alert), executar um comando (exec), quais os eventos a monitorizar (events), se queremos que seja escrito algo no syslog (syslog), etc..

 
Assim que tiverem criado um ficheiro de configuração, temos que efectuar algumas operações.
Copiar o ficheiro iwatch.xml e iwatch.dtd para /etc
 
cp iwatch.xml iwatch.dtd /etc
 
Copiar iwatch (o binário) para /usr/local/bin
cp iwatch /usr/local/bin
 
Para executar o iwatch em daemon mode, antes de colocarmos automático no arranque do computador, vamos experimentar
/usr/local/bin/iwatch -d -v
 
O parametro -d coloca o iwatch em daemon mode e o -v  coloca-o em verbose mode. Ao usarem o verbose mode, ele coloca no syslog as directorias em monitorização e quando acontece algum evento.
Vamos verificar se está em execução:
 
ps -aef | grep -i iwatch

root      3377     1  1 15:10 ?        00:00:00 /usr/bin/perl -T /usr/local/bin/iwatch -d -v
 
Agora, recordem as directorias que especificaram no ficheiro de configuração e façam testes.
Para que o iwatch fique em execução no reboot da máquina, em CentOS (e variantes Red Hat) podemos colocar o comando em /etc/rc.local
 
E já está. Um sistema completo de monitorização e notificação para o que precisarem. Muito simples e eficiente.
 

Aplicação Prática

Onde se pode aplicar isto?
Bem, imaginem que têm servidores expostos na Internet, e por questões de segurança, configuram dois servidores, um principal e outro secundário. O principal está na vossa rede interna e o secundário está exposto à Internet.
Os utilizadores alteram e actualizam o principal (interno) que automaticamente sincroniza as alterações para o externo, que contém uma firewall e que apenas deixa passar os portos do MySQL (para a replicação) e do rsync (ambos para tráfego vindo da rede interna), que é executado cada vez que há uma alteração no /var/www/html, que está a ser monitorizado pelo iwatch.
 
Simples, não é ?