Girar os logs antes de analisá-los parece uma boa ideia, desde que seus aplicativos não mantenham o arquivo de log aberto permanentemente. Se eles fizerem isso, girá-los não funcionará - mas, como você está escrevendo a estrutura de logging, você pode lidar com isso.
Se você quer um script simples, pode usar algo como o seguinte (pode ser feito em praticamente qualquer linguagem de script):
#! /bin/bash
process_line() {
# do the work here
echo "== $1 =="
}
logfile=$1
statefile=${logfile}.state
if [ -f ${statefile} ] ; then
processed=$(cat $statefile)
else
processed=0
fi
curline=0
IFS='
'
while read line ; do
if [ $curline -ge $processed ] ; then
echo processing $line
process_line "$line"
fi
curline=$(($curline+1))
done < ${logfile}
echo $curline > $statefile
Basicamente, ele salva onde processou a entrada em um arquivo separado ( $statefile
) e processa a entrada linha por linha a partir desse ponto (ignorando os já processados).
Isso exigiria um pouco mais de tratamento de erros, obviamente, e se a entrada for grande, não é ideal. (Pode ser melhor salvando um byte offset e procurando, ou usando dd bs=1 skip=$already_read count=$(($size-$already_read))
para canalizar para outro processo em vez de fazer as coisas linha por linha, mas eu usaria perl
se esse tipo de otimização fosse necessário.)
Como está, o script processará as linhas duas vezes se for interrompido. Você pode limitar a quantidade de "replay" atualizando o arquivo de estado após cada linha, em vez de uma vez no final.
Se você processar os logs e rotacioná-los, precisará ter cuidado com esses arquivos de estado. Eles precisariam ser girados também, e o script é executado uma vez após a rotação para processar as últimas linhas de saída.
Há uma coisa que esta abordagem não lida facilmente: linhas parciais. Se o aplicativo estiver sendo gravado enquanto o script é executado, há uma chance de o script ver uma última linha parcial. Não será capaz de dizer a diferença, por isso vai gravar como tendo sido processado. (Esse é um problema com o qual você precisará lidar com praticamente qualquer abordagem).
Isso pode ser evitado com um marcador EOL no formato de arquivo de log e verificando isso antes de processar a linha. Mas isso não é muito bonito.
Em vez de fazer o processamento em bash
no próprio script, você poderia usá-lo assim (substitua process_line
por echo
):
$ ./logger /var/log/app12.log | ./analyzer --logtype=app12
./analyzer
obterá os dados como entrada.