Como posso acionar um script para ser executado depois que o arquivo recebido pelo rsyncdaemon for alterado para uma determinada pasta?

2

Eu tenho vários servidores onde o rsyncd está sendo executado. Eu não uso um túnel ssh, mas o protocolo rsync nativo. Uma pasta dos arquivos sincronizados contém os arquivos que devem formar uma imagem iso. Sempre que um arquivo nessa pasta é carregado (empurrado de remoto para este servidor), ele deve recriar o arquivo iso automaticamente. Idealmente, apenas o conteúdo do arquivo ou as alterações de tamanho devem acionar isso porque quero mostrar a data da última alteração do iso dentro de uma página da Web onde os usuários podem baixá-lo e gravá-lo.

Como a iso é grande, quero criá-la em cada servidor se apenas um arquivo for alterado. Eu não quero sincronizar o iso em si

    
por Christian 09.09.2010 / 23:31

2 respostas

5

Isso é mais uma resposta ao Gilles, mas eu queria formatar um pequeno código; Uma maneira mais fácil de fazer o monitoramento dos arquivos alterados é armazenar um md5sum de md5sums do diretório, ala:

find /path/to/iso/data/ -type f -exec md5sum {} + | awk '{print $1}' | sort | md5sum | awk '{print $1}'

... que lhe dá a saída do tipo:

b843afc89097f0abc062e0d0e14d480b

Se você salvar isso em cada iteração do seu cron, é uma maneira muito rápida e eficaz de determinar se o conteúdo foi alterado no destino. Você poderia até mesmo construir um wrapper em torno do daemon rsync do xinetd; substitua a chamada pelo binário em /etc/xinetd.d/rsync:

server          = /usr/bin/rsync

... com um script:

server          = /path/to/script.sh

E, em seguida, no seu script, compare e faça a ação toda vez que o daemon sair com um status 0 válido. Isso é muito mais automatizado do que um cron job, com o benefício que ele só executa se você o codificar para o rsync exit 0. Algo como ... (código do psuedo aqui):

#!/bin/sh

/usr/bin/rsync "$*"

if [ $? -eq 0 ]; then
  OLDVALUE='cat /var/cache/isodata.txt'
  NEWVALUE='find /path/to/iso/data/ -type f -exec md5sum {} + | awk '{print $1}' | sort | md5sum | awk '{print $1}''
  if [ ${OLDVALUE} != ${NEWVALUE} ]; then
    -- run ISO making code --
    echo ${NEWVALUE} > /var/cache/isodata.txt
  fi
fi

Essa é a ideia geral para começar.

    
por 10.09.2010 / 02:54
3

A forma antiquada, portátil e desajeitada é executar o script de geração iso em intervalos regulares, seja por meio do cron ou com um while sleep loop (preferível se o intervalo não for muito maior que o tempo necessário para regenerar o ciclo iso). Para evitar a regeneração do iso, se os arquivos não tiverem sido alterados, faça isso apenas se [ -n "$(find -cnewer foo.iso -print -quit)" ] . Observe que isso não será acionado se alguns arquivos foram excluídos e nenhum foi alterado ou adicionado.

Uma maneira melhor, mas não portátil, é usar a API de monitoramento de alterações de arquivos da plataforma: fam no IRIX e alguns outros sistemas, kqueue no * BSD, inotify no Linux, etc. Tudo pode ser facilmente configurado para executar um comando se um arquivo for alterado (incluindo um diretório); Não sei se todos podem assistir a uma árvore de diretórios.

Uma maneira diferente seria colocar os arquivos em um sistema de arquivos userland (como o FUSE) que apenas passa as chamadas para o armazenamento subjacente, exceto que as modificações acionam a regeneração da iso.

O que quer que você faça, observe que um arquivo pode mudar enquanto você está regenerando a iso; Nesse caso, você tem duas estratégias. Você pode esperar até que a geração termine e comece de novo, o que é um desperdício. Ou você pode matar a geração iso e começar de novo, mas isso pode levar a um longo tempo sem uma atualização iso se os arquivos continuarem sendo modificados mais rapidamente do que a iso pode ser regenerada. Uma mistura dos dois nos quais você mata a geração iso, a menos que nenhuma iso tenha sido gerada em mais de X vezes, é uma solução razoável.

    
por 10.09.2010 / 01:14