Shell Script para análise de log Java [RESOLVIDO]

1. Shell Script para análise de log Java [RESOLVIDO]

Rafael Guedes
rat_guedes

(usa Ubuntu)

Enviado em 18/11/2014 - 18:34h

Prezados,
Estou necessitando de ajuda para a elaboração de um Shell Script, visto que meu conhecimento de comandos Linux é bem limitado.
Meu problema é o seguinte: Preciso escrever um script que faça a analise do log de um job Java.
Esse script deve varrer o arquivo de log em busca da expressão 'ERROR' e escrever em um arquivo chamado 'alerta.out', na mesma pasta do script, as linhas que contém tal expressão.
Caso não encontre nenhum 'ERROR', tal arquivo não deverá ser criado.
Esse script será chamado periodicamente por uma ferramenta de monitoramento e operação assistida, que dará alertas caso haja erros no job (ou seja, caso encontre o arquivo 'alerta.out').
Como o arquivo de log geralmente é muito grande, e também para que não sejam gerados alertas repetidos, o script deverá guardar de alguma maneira a última linha verificada, para que na próxima execução continue somente daí.
Pois bem, como o log do job é formatado em um padrão fixo, pelo Log4j, decidi armazenar em um arquivo chamado 'ult_dt_hr_verificada.out' o inicio da última linha verificada, que contém a data e hora.
A partir daí, o algoritmo seria procurar por essa data/hora no arquivo, descobrir o número dessa linha, e então procurar pelo padrão 'ERROR' somente dessa linha em diante, até o final do arquivo.

Começei a desenvolver o script, mas tive problemas com caracteres especiais no comando grep, entre outros.

A seguir, um exemplo de um trecho do arquivo de log:

[12/11/2014 10:42:05] [ INFO] {Carregador.java->processarArquivos} Removendo notas fiscais eletronicas invalidas...
[12/11/2014 10:42:75] [ INFO] {Carregador.java->processarArquivos} Carregando notas fiscais eletronicas...
[12/11/2014 10:43:13] [ ERROR] {Carregador.java->processarArquivos} Processando nota 211200084. Ocorreu um erro! Finalizando...
[12/11/2014 10:43:20] [ INFO] {Carregador.java->run} Processamento de carga de notas fiscais eletronicas finalizado.

O arquivo 'alerta.out' deveria ser criado com o conteúdo "[12/11/2014 10:43:13] [ ERROR] {Carregador.java->processarArquivos} Processando nota 211200084. Ocorreu um erro! Finalizando..." e o arquivo 'ult_dt_hr_verificada.out' deveria ser criado com o conteúdo "[12/11/2014 10:43:20]".


Eis o meu script, até o momento:

#! /bin/bash
FILE_DT_HR=ult_dt_hr_verificada.out
FILE=/u02/portal-j04.log
if [ -e "$FILE_DT_HR" ] ;
then
ULT_DATA_HORA_VERIFICACAO=$(tail -n 1 $FILE_DT_HR);
echo "Na execução anterior, a última linha verificada foi a de Data/Hora $ULT_DATA_HORA_VERIFICACAO";
else
echo "Arquivo $FILE_DT_HR necessário não encontrado. O script irá terminar. Para resolver o problema, criar este arquivo na mesma pasta do script, que deverá conter a informação de Data/Hora a partir da qual o script irá iniciar a varredura por erros, no formato [dd/MM/AAAA hh:mm:ss]";
exit 1;
fi
rm -f alerta.out
rm -f $FILE_DT_HR
ERROR=$(grep ERROR $FILE);
if [ ${#ERROR} -gt 1 ];
then
echo "Erro encontrado! Arquivo alerta.out gerado.";
echo "$ERROR">alerta.out;
#
#Exibida somente para teste
LINHA_ERRO=$(grep -n ERROR $FILE);
NUM_LINHA_ERRO=${LINHA_ERRO%%:*};
echo "Linha com erro ${NUM_LINHA_ERRO}";
#
#Calcula o total de linhas do arquivo
TOTAL_LINHAS=$(wc -l $FILE);
NUM_TOTAL_LINHAS=${TOTAL_LINHAS%% *};
echo "Total de linhas do arquivo: ${NUM_TOTAL_LINHAS}"
#
#Aqui dá erro. Seria necessário descobrir o numero da ultima linha verificada
ULT_LINHA_VERIFICADA=$(grep -n ${ULT_DATA_HORA_VERIFICACAO} $FILE);
echo "Numero da ultima linha verificada: ${ULT_LINHA_VERIFICADA}";
#
else
echo "Nenhum erro encontrado (busca realizada no arquivo $FILE pela string ERROR).";
fi
tail -n 1 $FILE | cut -c 1-21 > ult_dt_hr_verificada.out;
DT_HR_ULT_LINHA_VERIFICADA=$(tail -n 1 ult_dt_hr_verificada.out);
echo "Nesta execução, a última linha verificada foi a de Data/Hora $DT_HR_ULT_LINHA_VERIFICADA";


Ao tentar fazer "ULT_LINHA_VERIFICADA=$(grep -n ${ULT_DATA_HORA_VERIFICACAO} $FILE);" para pegar o número da última linha verificada, para então diminuir do total de linhas e verificar somente o resultado com "tail -n RESULTADO $FILE", dá um erro no grep.

Alguma sugestão, inclusive de um outro algoritmo, talvez mais simples ou melhor elaborado? Grato.




  


2. Re: Shell Script para análise de log Java [RESOLVIDO]

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 18/11/2014 - 18:57h

Bom , irei testar o 'código' , mas tente assim :


cat -n arquivo


cat -n mostra o arquivo, porem no inicio com o numero da linha , acho que isso iria lhe facilitar na hora de utilizar o grep

Não sei se compreendeu ,mas qualquer dúvida só postar aqui!

[]'s

T+


3. Re: Shell Script para análise de log Java [RESOLVIDO]

Rafael Guedes
rat_guedes

(usa Ubuntu)

Enviado em 18/11/2014 - 19:13h

Obrigado pelo retorno, Thihup.

Meu problema imediato é o seguinte, se conseguisse pegar o número da linha que contém a última data/hora verificada na execução anterior, daria um bom adiantamento. Tentei fazer isso com o comando:

ULT_LINHA_VERIFICADA=$(grep -n ${ULT_DATA_HORA_VERIFICACAO} $FILE);

A variável ULT_DATA_HORA_VERIFICACAO contem o valor [12/11/2014 10:43:20] (lido do arquivo 'ult_dt_hr_verificada.out'), dado o arquivo de exemplo. Acontece que o comando grep retorna o seguinte erro:

grep: [ ou [^ sem correspondente

Acho que devido aos caracteres '[' e ']' presentes no padrão.

P.s. Como o arquivo de log em produção tem um tamanho MUITO grande, não é aconselhável o uso do comando cat, pois em meus testes ele demora muitos minutos pra retornar! Por isso estou tentando resolver tudo com tails e greps.


4. Re: Shell Script para análise de log Java [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 18/11/2014 - 19:28h

Se o problema for esse, você pode eliminar estes caracteres ("[" e "]") usando a expressão abaixo, ao definir a variável "ULT_DATA_HORA_VERIFICACAO":


ULT_DATA_HORA_VERIFICACAO=`wc -m ult_dt_hr_verificada.out | awk '{print $1}'` ; ULT_DATA_HORA_VERIFICACAO=`cut -c 2-$((ULT_DATA_HORA_VERIFICACAO-2)) ult_dt_hr_verificada.out`



5. Re: Shell Script para análise de log Java [RESOLVIDO]

Rafael Guedes
rat_guedes

(usa Ubuntu)

Enviado em 19/11/2014 - 12:15h

Unnslacker, obrigado pelo retorno!
A forma indicada para retirar os colchetes funcionou perfeitamente, depois reservarei um tempo para estudar os comandos.
Agora, ao tentar fazer o grep com o novo padrão que está na variável (18/11/2014 10:42:00), continua dando erro, porém um erro diferente, acredito que ainda por causa de caracter especial, no caso o ":", veja: "grep: 10:42:00: No such file or directory".
Só que dessa vez vejo um problema mais complicado, pois não podemos retirar os ":", pois é assim que está no arquivo, logo, assim que devo procurar.
E agora?


6. Re: Shell Script para análise de log Java [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 19/11/2014 - 14:00h

Não, o erro não é o ":"; o erro agora é o espaço que existe entre a data e a hora, fazendo com que o grep interprete-o como um arquivo, e não como uma continuação da variável; o que pode ser feito agora é separar uma variável só para a data e outra só para a hora, assim:

#1 - Crie a variável "ULT_DATA_VERIFICACAO", para armazenar a data:

ULT_DATA_VERIFICACAO=`wc -m ult_dt_hr_verificada.out | awk '{print $1}'` ; ULT_DATA_VERIFICACAO=`cut -c 2-$((ULT_DATA_VERIFICACAO-11)) ult_dt_hr_verificada.out`


#2 - Crie a variável "ULT_HORA_VERIFICACAO", para armazenar a hora:

ULT_HORA_VERIFICACAO=`wc -m ult_dt_hr_verificada.out | awk '{print $1}'` ; ULT_HORA_VERIFICACAO=`cut -c 13-$((ULT_HORA_VERIFICACAO-2)) ult_dt_hr_verificada.out`


Os comandos fazem a mesma coisa da expressão anterior, a única diferença é que ele armazena os valores em variáveis diferentes (enquanto o anterior armazenava tudo na variável "ULT_DATA_HORA_VERIFICACAO")


7. Re: Shell Script para análise de log Java [RESOLVIDO]

Rafael Guedes
rat_guedes

(usa Ubuntu)

Enviado em 19/11/2014 - 16:10h

Unnslacker, obrigado mais uma vez pela valiosa ajuda.
A idéia de separar as variáveis funcionou perfeitamente.
Agora consigo saber qual a última linha foi verificada com o comando:

ULT_LINHA_VERIFICADA=$(grep -n "${ULT_DATA_VERIFICACAO} ${ULT_HORA_VERIFICACAO}" $FILE);

A partir dai irei completar a lógica do script.

Assim que terminar e testar postarei aqui para fechar o tópico como resolvido.

Att.


8. Re: Shell Script para análise de log Java [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 19/11/2014 - 16:34h

rat_guedes escreveu:

Unnslacker, obrigado mais uma vez pela valiosa ajuda.
A idéia de separar as variáveis funcionou perfeitamente.
Agora consigo saber qual a última linha foi verificada com o comando:

ULT_LINHA_VERIFICADA=$(grep -n "${ULT_DATA_VERIFICACAO} ${ULT_HORA_VERIFICACAO}" $FILE);

A partir dai irei completar a lógica do script.

Assim que terminar e testar postarei aqui para fechar o tópico como resolvido.

Att.


De nada; a lógica era bem essa mesmo: depois de separar a data e a hora em variáveis próprias, você conseguiria "uni-las por um espaço" dentro do grep (de modo que ele não confunda o dado da variável com um arquivo), igual como você fez;

Agora é só terminar de implementar e ver o resultado; boa sorte!


9. Re: Shell Script para análise de log Java [RESOLVIDO]

Rafael Guedes
rat_guedes

(usa Ubuntu)

Enviado em 19/11/2014 - 18:21h

Script finalizado, ao menos em uma primeira versão.

Nos testes iniciais funciona adequadamente: varre o arquivo desde a última linha verificada (pode repetir umas poucas, se várias linhas possuírem exatamente a mesma data/hora) até o fim em busca da string "ERRO" e caso encontre, escreve as linhas que a contem em um arquivo "alerta.out". Funciona bem caso exista um ou vários erros e também se for chamado em intervalos curtos ou longos, independente do tamanho do arquivo de log.

Sei que ainda falta ajustar/otimizar/embelezar/etc o script, mas é um bom resultado para uma primeira implementação, partindo de um "windows boy". :)

Agradeço a todos pela valiosa ajuda.

Eis o script:

#! /bin/bash
#Declarando as variáveis que são arquivos
FILE_ALERTA=alerta.out
FILE_DT_HR=ult_dt_hr_verificada.out
FILE=/u02/portal-nfc-j04.log
FILE_TEMP=temp.out
#
#A string a procurar no arquivo, que significa que houve um erro
STRING_DE_BUSCA=ERROR
#
#Testa se o arquivo que armazena a última linha do log que foi verificada está presente. Na primeira execução esse arquivo conterá algo como [01/01/1900 00:00:00]
if [ -e "$FILE_DT_HR" ] ;
then
ULT_DATA_VERIFICACAO=`wc -m ult_dt_hr_verificada.out | awk '{print $1}'` ; ULT_DATA_VERIFICACAO=`cut -c 2-$((ULT_DATA_VERIFICACAO-11)) ult_dt_hr_verificada.out`;
ULT_HORA_VERIFICACAO=`wc -m ult_dt_hr_verificada.out | awk '{print $1}'` ; ULT_HORA_VERIFICACAO=`cut -c 13-$((ULT_HORA_VERIFICACAO-2)) ult_dt_hr_verificada.out`;
echo "Na execução anterior, a última linha verificada foi a de Data/Hora $ULT_DATA_VERIFICACAO $ULT_HORA_VERIFICACAO";
echo "Iniciando verificação...";
#
#Se não existe o aqruivo, informa o erro, uma possível solução e finaliza o script
else
echo "Arquivo $FILE_DT_HR necessário não encontrado. O script irá terminar. Para resolver o problema, criar este arquivo na mesma pasta do script, que deverá conter a informação de Data/Hora a partir da qual o script irá iniciar a varredura por erros, no formato [dd/MM/AAAA hh:mm:ss]";
exit 1;
fi
#
#Apaga o arquivo com a última linha verificada na execução anterior e o possível arquivo de alerta criado naquela
rm -f alerta.out
rm -f $FILE_DT_HR
#
#Calcula o total de linhas do arquivo, o número da última linha verificada e finalmente a quantidade de linhas a verificar na presente execução
TOTAL_LINHAS=$(wc -l $FILE);
declare -i NUM_TOTAL_LINHAS;
NUM_TOTAL_LINHAS=${TOTAL_LINHAS%% *};
echo "Total de linhas do arquivo: ${NUM_TOTAL_LINHAS}"
ULT_LINHA_VERIFICADA=$(grep -n "${ULT_DATA_VERIFICACAO} ${ULT_HORA_VERIFICACAO}" $FILE);
declare -i NUM_ULT_LINHA_VERIFICADA;
NUM_ULT_LINHA_VERIFICADA=${ULT_LINHA_VERIFICADA%%:*};
echo "Ultima linha verificada: $NUM_ULT_LINHA_VERIFICADA";
declare -i LINHAS_A_VERIFICAR;
LINHAS_A_VERIFICAR=$NUM_TOTAL_LINHAS-$NUM_ULT_LINHA_VERIFICADA;
echo "Total de linhas a verificar: $LINHAS_A_VERIFICAR";
#
#Cria um arquivo temporário, somente com as linhas a verificar
tail -n $LINHAS_A_VERIFICAR $FILE > $FILE_TEMP;
#
#Armazena na variável as possíveis linhas com erros
ERROS=$(grep $STRING_DE_BUSCA $FILE_TEMP);
#
#Apaga o arquivo temporário
rm -f $FILE_TEMP;
#
#Se existe algo na variável, algum erro foi encontrado, deve-se criar o arquivo de alerta
if [ ${#ERROS} -gt 1 ];
then
echo "Erro encontrado! Arquivo alerta.out gerado.";
echo "$ERROS">$FILE_ALERTA;
else
echo "Nenhum erro encontrado.";
fi
#
#Armazena no arquivo a última linha verificada nessa execução (Sempre a última do arquivo).
tail -n 1 $FILE | cut -c 1-21 > $FILE_DT_HR;
DT_HR_ULT_LINHA_VERIFICADA=$(tail -n 1 $FILE_DT_HR);
echo "Busca realizada no arquivo $FILE pela string $STRING_DE_BUSCA da linha $NUM_ULT_LINHA_VERIFICADA até a última.";
echo "Nesta execução, a última linha verificada foi a de Data/Hora $DT_HR_ULT_LINHA_VERIFICADA";
echo "Busca de erros finalizada."







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts