inotifywatch: continue vigiando após a rotação do arquivo

2

Estou tentando escrever um script que use inotifywatch para observar alterações em um arquivo de log. Se uma mensagem específica for gravada no arquivo de log, ela deverá ativar uma determinada função. O script existe atualmente desta forma básica:

while inotifywait -e modify /var/log/auth.log
do
  alert=$(tail -n1 /var/log/auth.log | grep -E -o ".{0,7}password")
  if [[ $alert == "Failed password" ]]
  then
   echo "FAILURE" >> test.log
  elif [[ $alert == "cepted password" ]]
  then
   echo "LOGIN" >> test.log
  fi
done

Tudo funciona bem - até o ponto em que o arquivo de registro assistido por inotifywatch é rotacionado . Então deixa de funcionar. Eu presumo que é porque durante a rotação o arquivo assistido é renomeado e não é mais escrito para depois e um novo arquivo com o nome antigo é criado em seu lugar que inotify nunca foi dito para assistir em primeiro lugar.

Eu tentei contornar isso mudando de inotifywatch para usando tail -f , mas o mesmo problema parece ser aplicado também.

Agora percebo que isso provavelmente poderia ser resolvido com a criação de uma enorme if -estrutura na qual inotifywatch não apenas assiste a modify , mas também cria arquivos e reinicia um relógio para modificação. Mas eu gosto de manter as coisas simples, então alguém sabe se há uma maneira mais simples? (E, por favor, não, eu não quero usar soluções pré-fabricadas como o fail2ban etc. - a parte interessante para mim é criar coisas como essa com ferramentas simples.)

    
por Nick 18.12.2016 / 10:04

2 respostas

4

inotify é usado para monitorar arquivos em um diretório pelo inode, não pelo nome. Quando o arquivo é girado, seu conteúdo não muda mais (exceto por um curto período, até que os daemons sejam recarregados para que usem o arquivo de log recém-criado)

AFAIK, tail -f usa o sistema inotify, por isso não ajuda. Mas se você tiver uma solução de trabalho com tail -f , use tail --follow=name (ou tail -F ) se isso for suportado pela sua versão de tail (a cauda POSIX não suporta isso). O tail irá então monitorar o arquivo identificado pelo seu nome de arquivo. Aqui está um trecho da página man:

With --follow (-f), tail defaults to following the file descriptor, which means that even if a tail'ed file is renamed, tail will con‐ tinue to track its end. This default behavior is not desirable when you really want to track the actual name of the file, not the file descriptor (e.g., log rotation). Use --follow=name in that case. That causes tail to track the named file in a way that accommodates renaming, removal and creation.

[atualização]

Exemplo de uso:

tail -n0 -F my_file.log \
| while read -r log_line; do
    do_something_with "$log_line"
done

Por causa do pipe, o loop while é executado em um subprocesso, o que pode causar problemas se você quiser modificar variáveis fora do loop. Se você usa bash , você pode querer usar essa sintaxe alternativa que não tem esse efeito indesejável (mas é menos legível):

while read -r log_line; do
    do_something_with "$log_line"
done < <(tail -n0 -F my_file.log)
    
por 18.12.2016 / 10:49
2

Isso pode ser feito com inotifywait com um verso:

inotifywait -e move_self -e modify -m /path/to/some/file | awk '$2=="MODIFY" {system("/bin/echo Yes")}'

O sinalizador -m continua monitorando o arquivo indefinidamente, para os eventos move_self (que permite monitorar a mudança de nome de um arquivo ou diretório) e modificar , passando a saída para um comando awk que elimina eventos move_self , executando o comando dentro do conjunto de parênteses system para cada < em> modificar evento. Você terá que escrever seu próprio script de shell no lugar do meu comando echo . Por favor, preste atenção aos vários conjuntos de apóstrofos e aspas.

    
por 18.12.2016 / 11:01