Quero executar automaticamente um script sempre que novos arquivos são copiados para um diretório específico. Em outras palavras, existe uma maneira no Linux de "observar" um diretório para alterações e executar algo em resposta à mudança?
Quero executar automaticamente um script sempre que novos arquivos são copiados para um diretório específico. Em outras palavras, existe uma maneira no Linux de "observar" um diretório para alterações e executar algo em resposta à mudança?
Respostas:
Se você tiver sorte o suficiente para estar em uma distribuição baseada no debian apt-get install dnotify
,. Outras distribuições provavelmente têm algo parecido - procure o dnotify
nome.
O dnotify é um programa simples baseado na API do dnotify do kernel 2.4.19 + do Linux. O dnotify pode executar um comando especificado sempre que o conteúdo de um diretório específico for alterado. É executado a partir da linha de comando e recebe dois argumentos: um ou mais diretórios para monitorar e um comando para executar sempre que um diretório é alterado. As opções controlam em quais eventos disparar: quando um arquivo foi lido no diretório, quando um foi criado, excluído e assim por diante.
Se você quiser lidar com isso dentro do seu próprio programa, dnotify também é a API que você deseja usar.
emerge inotify-tools
Você pode executar um script com as ferramentas inotify, algo como isto. Ele observará o diretório quanto a alterações nos arquivos modificados, novos e excluídos, e executará o script.
#!/bin/sh
while inotifywait -e modify -e create -e delete /home/me/code; do
rsync [options] /home/me/code/ /media/nfs/code/
done
incron é basicamente o que você quer, eu acho. Ele usa inotify como mecanismo de notificação (que, como outros já apontaram, substitui o dnotify), mas não requer um script que seja executado continuamente, usando inotifywait ou similar (embora, obviamente, o daemon incron esteja em execução o tempo todo). 'Crontabs' em todo o sistema e 'crontabs' do usuário são suportados de maneira semelhante ao cron padrão, mas, em vez de especificar horários como acionadores, são utilizados eventos inotify e nomes de arquivos / diretório.
O incron é empacotado para muitas distribuições, incluindo Ubuntu e Debian, acredito.
entr é a ferramenta de notificação de arquivos mais simples e mais fácil de compor que já vi. Seu uso é otimizado para assistir arquivos, e não diretórios, mas também pode resolver o seu caso.
Para detectar e atuar no arquivo adicionado, combine-o com outras ferramentas, como por exemplo make
. entr
não envia o nome ou algo assim, simplesmente executa o que você pediu para executar.
Para verificar se há arquivos adicionados em um diretório:
## entr exits with rc=0 when terminated
## rc=1 when watched files go away or don't exist to begin with
## rc=2 when new files arrive in watched directories
until echo /path/to/directory_to_watch | entr -d do_stuff
do sleep 1; done
Se você também deseja agir quando um arquivo existente é alterado:
## Here's why it comes in handy that entr exits when new files are added --
## find gets re-run.
until find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/* |
entr -d do_stuff
do sleep 1; done
... e é aí que o mecanismo de loop é útil, pois a find
expressão será executada novamente se um arquivo for adicionado.
Se você deseja um melhor tratamento de erros e deseja garantir que as coisas sejam executadas apenas uma vez por arquivo adicionado / removido, as coisas ficam um pouco peculiares, mas, para esses casos simples, é brilhante.
EDIT: Se você quiser fazer isso no nível do sistema, algo como incron , basta adicionar o script ao seu gerenciador de processos favorito (como s6 , runit , systemd ou sysvinit e pular o loop:
#!/bin/bash
exec entr -d do_stuff < <(find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/*)
A exec
substituição e o processo ( <(...)
) são importantes ao executar a partir de um gerenciador de processos, para lidar com a sinalização corretamente (ou seja, para tirar o shell do caminho).