Como extrair logs entre a hora atual e os últimos 15 minutos

0

Eu quero extrair os logs entre o registro de data e hora atual e 15 minutos antes e enviei um e-mail para as pessoas configuradas. Eu desenvolvi o script abaixo, mas não está funcionando corretamente; alguém pode me ajudar?? Eu tenho um arquivo de log contendo esse padrão:

[2016-05-24T00:58:04.508-04:00] [oim_server1] [TRACE:32] [] [oracle.iam.scheduler.impl.quartz] [tid: OIMQuartzScheduler_QuartzSchedulerThread] [userId: oiminternal] [ecid: 0000LI6NBsP4yk4LzUS4yW1NBABd000003,1:21904] [APP: oim#11.1.2.0.0] [SRC_CLASS: oracle.iam.scheduler.impl.quartz.QuartzJob] [SRC_METHOD: <init>] Constructor  QuartzJob
[2016-05-24T00:58:04.508-04:00] [oim_server1] [TRACE:32] [] [oracle.iam.scheduler.impl.quartz] [tid: OIMQuartzScheduler_QuartzSchedulerThread] [userId: oiminternal] [ecid: 0000LI6NBsP4yk4LzUS4yW1NBABd000003,1:21904] [APP: oim#11.1.2.0.0] [SRC_CLASS: oracle.iam.scheduler.impl.quartz.QuartzJob] [SRC_METHOD: <init>] Constructor  QuartzJob
[2016-05-24T00:58:04.513-04:00] [oim_server1] [TRACE:32] [] [oracle.iam.scheduler.impl.quartz] [tid: OIMQuartzScheduler_Worker-1] [userId: oiminternal] [ecid: 0000LI6NBsP4yk4LzUS4yW1NBABd000003,1:21908] [APP: oim#11.1.2.0.0] [SRC_CLASS: oracle.iam.scheduler.impl.quartz.QuartzTriggerListener] [SRC_METHOD: triggerFired] Trigger state 0
[2016-05-24T00:58:04.515-04:00] [oim_server1] [TRACE:32] [] [oracle.iam.scheduler.impl.quartz] [tid: OIMQuartzScheduler_Worker-1] [userId: oiminternal] [ecid: 0000LI6NBsP4yk4LzUS4yW1NBABd000003,1:21908] [APP: oim#11.1.2.0.0] [SRC_CLASS: oracle.iam.scheduler.impl.quartz.QuartzTriggerListener] [SRC_METHOD: triggerFired] Trigger state 0
[2016-05-24T00:58:04.516-04:00] [oim_server1] [TRACE:32] [] [oracle.iam.scheduler.impl.quartz] [tid: OIMQuartzScheduler_Worker-1] [userId: oiminternal] [ecid: 0000LI6NBsP4yk4LzUS4yW1NBABd000003,1:21908] [APP: oim#11.1.2.0.0] [SRC_CLASS: oracle.iam.scheduler.impl.quartz.QuartzTriggerListener] [SRC_METHOD: triggerFired] Trigger Listener QuartzTriggerListener.triggerFired(Trigger trigger, JobExecutionContext ctx)
[2016-05-24T01:00:04.513-04:00] [oim_server1] [WARNING] [] [oracle.iam.scheduler.vo] [tid: OIMQuartzScheduler_Worker-7] [userId: oiminternal] [ecid: 0000LI6NBsP4yk4LzUS4yW1NBABd000003,1:21956] [APP: oim#11.1.2.0.0] IAM-1020021 Unable to execute job : CmyAccess Flat File WD Candidate with Job History Id:1336814[[
org.identityconnectors.framework.common.exceptions.ConfigurationException: Directory does not contain normal files to read HR-76
    at org.identityconnectors.flatfile.utils.FlatFileUtil.assertValidFilesinDir(FlatFileUtil.java:230)
    at org.identityconnectors.flatfile.utils.FlatFileUtil.getDir(FlatFileUtil.java:176)
    at org.identityconnectors.flatfile.utils.FlatFileUtil.getFlatFileDir(FlatFileUtil.java:182)
    at org.identityconnectors.flatfile.FlatFileConnector.executeQuery(FlatFileConnector.java:134)
    at org.identityconnectors.flatfile.FlatFileConnector.executeQuery(FlatFileConnector.java:58)
    at org.identityconnectors.framework.impl.api.local.operations.SearchImpl.rawSearch(SearchImpl.java:105)
    at org.identityconnectors.framework.impl.api.local.operations.SearchImpl.search(SearchImpl.java:82)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.identityconnectors.framework.impl.api.local.operations.ConnectorAPIOperationRunnerProxy.invoke(ConnectorAPIOperationRunnerProxy.java:93)
    at com.sun.proxy.$Proxy735.search(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.identityconnectors.framework.impl.api.local.operations.ThreadClassLoaderManagerProxy.invoke(ThreadClassLoaderManagerProxy.java:107)
    at com.sun.proxy.$Proxy735.search(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.identityconnectors.framework.impl.api.BufferedResultsProxy$BufferedResultsHandler.run(BufferedResultsProxy.java:162)

O script que escrevi conta os erros encontrados e os armazena em um arquivo com o número; Se a contagem de erros aumentar, ele executará o script e enviará um email. Eu posso configurar o cron para isso, mas o script que eu escrevi não está funcionando bem. Alguém pode me ajudar a extrair logs entre a hora atual e os últimos 15 minutos e gerar um arquivo temporário?

LogDir=/data/app/Oracle/Middleware/user_projects/domains/oim_domain/servers/oim_server1/logs
[email protected]
SUBJECT=Failed
MESSAGE="Scheduler failed"
SMTP="SMTPHOSTNAME"
[email protected]



   NOW=$(date +"%FT%T.000%-04:00")
T2=$(date --date='15 minutes ago' +"%FT%T.000%-04:00")
OUT=/tmp/oim_server1-diagnostic_$(date +%F-%H-%M).log


find $LogDir -mmin -15 -name "oim_server1-diagnostic.log" > files.txt

count=0;
if [ -f lastCount ]; then
 count=$(cat lastCount)
fi


while read file
do
  echo "reading file \n " $file
  currentCount=$(grep -c 'Directory does not contain normal files to read HR-76' $file)
  if [  $currentCount -ne $count  -a  $currentCount -ne 0  ];then
    echo "Error Found " $currentCount
    awk -v TSTART="[$T2]" -v TEND="[$NOW]" '$1>=TSTART && $1<=TEND' $LogDir/oim_server1-diagnostic.log > "$OUT"
    test -s $OUT &&
      echo -e "$MESSAGE" | mailx -S smtp="$SMTP" -a "$OUT" -r "$SENDER" -s "$SUBJECT" "$EMAIL1"
    rm -f "$OUT"
  fi
  echo $currentCount > lastCount
done < files.txt

Este script está extraindo os logs, mas não no formato apropriado. O maior log que eu estou encontrando com

(grep -c 'Directory does not contain normal files to read HR-76' $file)

Eu quero extrair todos os logs entre dois timestamps. Algumas linhas podem não ter o timestamp, mas também quero essas linhas. Em suma, eu quero cada linha que cai sob dois carimbos de tempo. Este script está me dando arquivo de log só tem timestamp e descanse todas as linhas estão faltando alguma sugestão ??? Por favor, note que o carimbo de hora de início ou o carimbo de hora de término pode não estar presente em todas as linhas do log, mas eu quero cada linha entre esses dois carimbos de hora. Geração de amostra do log acima mencionado :::

[2016-05-24T01:00:04.513-04:00] [oim_server1] [WARNING] [] [oracle.iam.scheduler.vo] [tid: OIMQuartzScheduler_Worker-6] [userId: oiminternal] [ecid: 0000LIt5i3n4yk4LzU^AyW1NEPxf000002,1:23444] [APP: oim#11.1.2.0.0] IAM-1020021 Unable to execute job : CmyAccess Flat File WD Employee with Job History Id:46608[[   
    
por Puneet Khullar 24.05.2016 / 11:56

3 respostas

1

Você quase tem isso.

Passo 1

No GNU e no Linux e talvez em outros sistemas, o comando date pode ser usado para imprimir um formato arbitrário para uma especificação de tempo, dada uma expressão de tempo fácil de usar. Por exemplo, posso obter uma string representando o tempo de 15 minutos no passado usando isto:

 date --date='15 minutes ago'

Você praticamente fez isso com seu código, embora com menos eficiência. Mas você deixou de fora os microssegundos. Presumivelmente, você não se importa com eles, mas precisa combiná-los. O fuso horário pode ser feito com '%: z', mas presumivelmente, você precisa coincidir com o fuso horário existente; as coisas podem quebrar logo após o horário de verão mudar. Se você tiver que se preocupar com vários fusos horários, precisará de um regex ou da solução do Sobrique. Emptor de advertência, você provavelmente poderia se safar:

NOW=$(date +"%FT%T.000%-04:00")
T2=$(date --date='15 minutes ago' +"%FT%T.000%-04:00")

Etapa 2

Você pode usar seu NOW e T2 como entradas para awk . A correspondência baseada em strings funcionará muito bem aqui, mas o awk permite que você se certifique de que cada linha se encaixe no intervalo de tempo necessário fazendo comparações de cadeia maior que e menor que.

awk -v TSTART="[$T2]" -v TEND="[$NOW]" '$1>=TSTART && $1<=TEND'

Etapa 3 (NOVO)

Você precisa obter as linhas de log sem timestamp entre as linhas com registro de data e hora. Portanto, usamos o código awk acima para corresponder às linhas de timestamp e, quando o timestamp estiver no intervalo correto, definir um sinalizador. Somente quando o sinalizador é definido como 1, a linha atual é impressa.

awk -v TSTART="[$T2]" -v TEND="[$NOW]" \
'/^\[[^ ]*\] / { log = ($1>=TSTART && $1<=TEND) } log { print }' 

Etapa 4

Como de costume, redirecione a saída, mas você deve observar que, se estiver executando o script a cada 15 minutos, seu código de redirecionamento atual substituirá o mesmo arquivo porque% H não será alterado em pelo menos três dessas execuções. Melhor torná-lo% H-% M ou algo assim. Mas não há necessidade de nenhum redirecionamento para o arquivo. Você pode enviá-lo diretamente para o correio (a menos que você realmente precise do anexo):

{  
   echo "$MESSAGE"; echo
   awk -v TSTART="[$T2]" -v TEND="[$NOW]" '$1>=TSTART && $1<=TEND' $LogDir/oim_server1-diagnostic.log    
} | mailx -S smtp="$SMTP" -r "$SENDER" -s "$SUBJECT" "$EMAIL1"

O resto do seu script deve funcionar como está.

No entanto, na configuração acima, agora você não recebe um anexo que pode ser salvo facilmente com o registro de data e hora relevante. E talvez você não queira enviar mensagens se não houver saída. Então você poderia fazer algo assim:

OUT=/tmp/oim_server1-diagnostic_$(date +%F-%H-%M)
awk -v TSTART="[$T2]" -v TEND="[$NOW]" '$1>=TSTART && $1<=TEND' $LogDir/oim_server1-diagnostic.log > "$OUT"
test -s $OUT && 
echo -e "$MESSAGE" | mailx -S smtp="$SMTP" -a "$OUT" -r "$SENDER" -s "$SUBJECT" "$EMAIL1"
rm -f "$OUT"

Isso limpa depois de si mesmo, para que você não tenha muitos arquivos de log de diagnóstico por aí.

    
por 24.05.2016 / 14:16
0

As expressões regulares não são uma boa opção para a correspondência de carimbos de data / hora, pois eles realmente não "entendem" valores numéricos. Então, em vez disso, sugiro analisar o registro de data e hora:

#!/usr/bin/env perl
use strict;
use warnings;

use Time::Piece; 

my $now = time();
my $last = $now - 15 * 60; 

while ( <> ) { 
   my ( $timecode ) = m/\[([^\.]+)/;
   print $timecode;
   my $t = Time::Piece -> strptime ( $timecode, '%Y-%m-%dT%H:%M:%S' );  
   print if $t > $last;
}

Isso pode fazer uma linha como:

perl -MTime::Piece -ne 'print if Time::Piece -> strptime ( m/\[([^\.]+)/, '%Y-%m-%dT%H:%M:%S' ) > time()  - 15 * 60'
    
por 24.05.2016 / 13:20
0

Eu usaria:

awk -v limit="$(date -d '15 minutes ago' +'[%FT%T')" '
  $0 >= limit' < log-file

Isso ignora os possíveis problemas que você pode ter duas horas por ano quando as compensações do GMT vão de -04: 00 a -05: 00 e de volta se a hora de verão se aplicar ao seu fuso horário.

date -d é específico do GNU, mas você já está usando.

    
por 24.05.2016 / 13:44