Usando inotifywait junto com vim

12

Eu tenho script simples que monitora arquivo para alterações e rsyncs com cópia remota:

#!/bin/bash

while inotifywait -e close_write somefile
do
    rsync somefile [email protected]:./somefile
done

Funciona muito bem com o nano, mas falha com o vim. Quando eu uso o nano, ele gera:

somefile CLOSE_WRITE,CLOSE   

e inicia o próximo loop esperando por outra edição.

Quando eu uso o vim, não há saída, o script apenas fecha com o código de saída 0.

Eu fiz algumas pesquisas e descobri que close_write é o parâmetro certo para iniciar o initofywait junto com o vim (primeiro eu queria usar o evento modify), mas por alguma razão ele falha por mim.

    
por adam767667 08.03.2015 / 14:18

1 resposta

12

Os editores podem seguir várias estratégias para salvar um arquivo. As duas principais variantes são substituir o arquivo existente ou gravar em um novo arquivo e movê-lo no lugar. Escrever em um novo arquivo e movê-lo para o lugar tem a boa propriedade de que, a qualquer momento, a leitura do arquivo fornece uma versão completa do arquivo (em um instante o antigo, no instante seguinte, o novo). Se o arquivo for sobrescrito no lugar, há um tempo durante o qual ele está incompleto, o que é problemático se algum outro programa o acessa naquele momento ou se o sistema travar.

O Nano aparentemente substitui o arquivo existente. Seu script detecta o ponto quando ele termina de gravar (o evento close_write ) e executa rsync nesse ponto. Observe que é possível que o rsync capture uma versão incompleta do arquivo, se você salvar duas vezes em sucessão rápida, antes que o rsync tenha concluído seu trabalho desde o primeiro salvamento.

Vim, por outro lado, usa a estratégia write-then-move - algo para o efeito de

echo 'new content' >somefile.new
mv -f somefile.new somefile

O que acontece com a versão antiga do arquivo é que ele é excluído no ponto em que a nova versão é colocada no lugar. Neste ponto, o comando inotifywait retorna, porque o arquivo que foi informado para assistir não existe mais. (O novo somefile é um arquivo diferente com o mesmo nome.) Se o Vim tivesse sido configurado para fazer um arquivo de backup, o que aconteceria seria algo como

echo 'new content' >somefile.new
ln somefile somefile.old
mv -f somefile.new somefile

e inotifywait agora estariam assistindo ao backup.

Para obter mais informações sobre estratégias de salvamento de arquivos, consulte Como é possível fazer uma atualização ao vivo enquanto um programa está rodando? e Permissões de arquivo e salvamento

O Vim pode ser instruído a usar a estratégia de substituição: desative o backupcopy opção ( :set nobackupcopy ). Isso é arriscado, conforme indicado acima.

Para lidar com as duas estratégias de salvamento, assista ao diretório e filtre os eventos close_write e moved_to para somefile .

inotifywait -m -e close_write,moved_to --format %e/%f . |
while IFS=/ read -r events file; do
  if [ "$file" = "somefile" ]; then
    …
  fi
done
    
por 09.03.2015 / 01:16