/ / Persistent AWK Program - bash, awk, log4j

Programma AWK persistente: bash, awk, log4j

Sono stato incaricato di scrivere uno script BASH perfiltrare i file log4j e collegarli su netcat a un altro host. Uno dei requisiti è che lo script deve tenere traccia di ciò che ha già inviato al server e non inviarlo nuovamente a causa dei vincoli di licenza sul server ricevente (il prodotto sul server è concesso in licenza su un modello data-per-day) .

Per ottenere il filtro sto usando AWKincapsulato in uno script BASH. Il componente BASH funziona bene - è il programma AWK che mi sta dando dolore quando provo a ricordarmi cosa è già stato inviato al server. Lo sto facendo afferrando il timestamp di una linea ogni volta che una linea corrisponde al mio pattern. Alla fine del programma, l'ultimo timestamp viene scritto su un file nascosto nella directory di lavoro corrente. Nelle esecuzioni successive del programma AWK leggerà questo file in una variabile. Ora ogni volta che una linea corrisponde al modello, anche il timbro temporale viene confrontato con quello della variabile, se è più recente viene stampato, altrimenti non lo è.

Uscita desiderata:

INFO 2012-11-07 09: 57: 12,479 [[artefatto].connector.http.mule.default.receiver.02] org.mule.api.processor.LoggerMessageProcessor: MsgID = 5017f1ff-1dfa-48c7-a03c-ed3c29050d12 InteractionStatus = Accept InteractionDateTime = 2012-08-07T16: 57: 33,379 + 12: 00 Rivenditore = CTCT RequestType = RemoteReconnect

File nascosto:

2012-10-11 12: 08: 19,918

Quindi questa è la teoria, ora il mio problema.

Lo script funziona bene per esempi inventati / banali come:

INFO 2012-11-07 09: 57: 12,479 [[artefatto].connector.http.mule.default.receiver.02] org.mule.api.processor.LoggerMessageProcessor: MsgID = 5017f1ff-1dfa-48c7-a03c-ed3c29050d12 InteractionStatus = Accept InteractionDateTime = 2012-08-07T16: 57: 33,379 + 12: 00 Rivenditore = CTCT RequestType = RemoteReconnect

Tuttavia, se lo eseguo su un file di registro completocon tracce di stack ecc., i livelli di indentazione sembrano rovinare il mio programma. La prima esecuzione del programma produrrà i risultati desiderati: le linee di corrispondenza verranno stampate e il timestamp più recente verrà scritto nel file nascosto. Eseguirlo di nuovo è quando il problema si presenta. L'output del programma contiene le linee indentate tratte da tracce di stack ecc. (Vedi il blocco sottostante) e non riesco a capire perché, quindi inserisce il file nascosto mentre l'ultima riga corrispondente non contiene un timestamp e alcuni rifiuti sono scritto su di esso rendendo inutili ulteriori corse.

Uscita indesiderata:

a package.reverse.domain.SomeClass.someMethod (SomeClass.java:233) a package.reverse.domain.processor.SomeClass.process (SomeClass.java:129) a package.reverse.domain.processor.someClass.someMethod (SomeClassjava: 233) a package.reverse.domain.processor.SomeClass.process (SomeClass.java:129)

File nascosto dopo:

package.reverse.domain.process (SomeClass.java:129)

Il mio programma awk:

FNR == 1 {
CMD = "basename " FILENAME
CMD | getline FILE;
FILE = "." FILE ".last";
if (system("[ -f "FILE" ]") == 0) {
getline FIRSTLINE < FILE;
close(FILE);
print FIRSTLINE;
}
else {
FIRSTLINE = "1970-01-01 00:00:00,000";
}
}
$0 ~ EXPRESSION {
if (($2 " " $3) > FIRSTLINE) {
print $0;
LASTLINE=$2 " " $3;
}
}
END {
if (LASTLINE != "") {
print LASTLINE > FILE;
}
}

Qualsiasi aiuto per scoprire perché questo sta accadendo sarebbe molto apprezzato.

AGGIORNARE:

Script BASH:

#!/bin/bash
while getopts i:r:e:h:p: option
do
case "${option}"
in
i) INPUT=${OPTARG};;
r) RULES=${OPTARG};;
e) PATFILE=${OPTARG};;
h) HOST=${OPTARG};;
p) PORT=${OPTARG};;
?) printf "Usage: %s: -i <"file1.log file2.log"> -r <"rules1.awk rules2.awk"> -e <"patterns.pat"> -h <host> -p <port>n" $0;
exit 1;
esac
done

#prepare expression with sed
EXPRESSION=`cat $PATFILE | sed ":a;N;$!ba;s/n/|/g"`;
EXPRESSION="^(INFO|DEBUG|WARNING|ERROR|FATAL)[[:space:]]{2}[[:digit:]]{4}\\-[[:digit:]]{1,2}\\-[[:digit:]]{1,2}[[:space:]][[:digit:]]{1,2}:[[:digit:]]{2}:[[:digit:]]{2},[[:digit:]]{3}.*"$EXPRESSION".*";

#Make sure the temp file is empty
echo "" > .temp;

#input through awk.
for file in $INPUT
do
awk -v EXPRESSION="$EXPRESSION" -f $RULES $file >> .temp;
done

#send contents of file to splunk indexer over udp
cat .temp;
#cat .temp | netcat -t $HOST $PORT;

#cleanup temporary files
if [ -f .temp ]
then
rm .temp;
fi

Patterns File (Le cose che voglio abbinare):

Warning
Exception

Scritta Awk come sopra.

Example.log

info  2012-09-04 16:00:11,638 [[adr-com-adaptor-stub].connector.http.mule.default.receiver.02] nz.co.amsco.interop.multidriveinterop: session not initialised
error 2012-09-04 16:00:11,639 [[adr-com-adaptor-stub].connector.http.mule.default.receiver.02] nz.co.amsco.adrcomadaptor.processor.comadaptorprocessor: nz.co.amsco.interop.exceptions.systemdownexception
nz.co.amsco.interop.exceptions.systemdownexception
at nz.co.amsco.adrcomadaptor.processor.comadaptorprocessor.getdeviceconfig(comadaptorprocessor.java:233)
at nz.co.amsco.adrcomadaptor.processor.comadaptorprocessor.process(comadaptorprocessor.java:129)
at org.mule.processor.chain.defaultmessageprocessorchain.doprocess(defaultmessageprocessorchain.java:99)
at org.mule.processor.chain.abstractmessageprocessorchain.process(abstractmessageprocessorchain.java:66)
at org.mule.processor.abstractinterceptingmessageprocessorbase.processnext(abstractinterceptingmessageprocessorbase.java:105)
at org.mule.processor.asyncinterceptingmessageprocessor.process(asyncinterceptingmessageprocessor.java:90)
at org.mule.processor.chain.defaultmessageprocessorchain.doprocess(defaultmessageprocessorchain.java:99)
at org.mule.processor.chain.abstractmessageprocessorchain.process(abstractmessageprocessorchain.java:66)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:105)
at org.mule.interceptor.AbstractEnvelopeInterceptor.process(AbstractEnvelopeInterceptor.java:55)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:105)

Uso:

./filter.sh -i "Esempio.log" -r "rules.awk" -e "patterns.pat" -h host -p porta

Nota che l'host e la porta sono entrambi inutilizzati in questa versione poiché l'output è appena lanciato su stdout.

Quindi se eseguo questo ottengo il seguente risultato:

info 16/09/2012 alle 16:00:11.638 [[adr-com-adapter-stub] .connector.http.mule.default.receiver.02] nz.co.amsco.interop.multidriveinterop: sessione non inizializzata errore 2012-09-04 16: 00: 11,639 [[adr-com-adapter-stub] .connector.http.mule.default.receiver.02] nz.co.amsco.adrcomadaptor.processor.comadaptorprocessore: nz.co. amsco.interop.exceptions.systemdownexception a nz.co.amsco.adrcomadaptor.processor.comadaptorprocessor.getdeviceconfig (comadaptorprocessor.java:233) a nz.co.amsco.adrcomadaptor.processor.comadaptorprocessor.process (comadaptorprocessor.java:129)

Se lo eseguo di nuovo sullo stesso file immutato, non dovrei ottenere output, tuttavia, sto vedendo:

nz.co.amsco.adrcomadaptor.processor.comadaptorprocessor.process (comadaptorprocessor.java:129)

Non sono stato in grado di determinare perché questo sta accadendo.

risposte:

1 per risposta № 1

Non hai fornito alcun esempio di input che potesse riprodurre il tuo problema, quindi cominciamo semplicemente a pulire il tuo script e ad andare da lì. Cambiarlo in questo:

BEGIN{
expression = "^(INFO|DEBUG|WARNING|ERROR|FATAL)[[:space:]]{2}[[:digit:]]{4}-[[:digit:]]{1,2}-[[:digit:]]{1,2}[[:space:]][[:digit:]]{1,2}:[[:digit:]]{2}:[[:digit:]]{2},[[:digit:]]{3}.*Exception|Warning"
# Do you really want "(Exception|Warning)" in brackets instead?
# As written "Warning" on its own will match the whole expression.
}

FNR == 1 {
tstampFile = "/" FILENAME ".last"
sub(/.*//,".",tstampFile)

if ( (getline prevTstamp < tstampFile) > 0 ) {
close(tstampFile)
print prevTstamp
}
else {
prevTstamp = "1970-01-01 00:00:00,000"
}

nextTstamp = ""
}

$0 ~ expression {
currTstamp = $2 " " $3
if (currTstamp > prevTstamp) {
print
nextTstamp = currTstamp
}
}

END {
if (nextTstamp != "") {
print nextTstamp > tstampFile
}
}

Ora hai ancora un problema? In tal caso, mostraci come esegui lo script, ovvero il comando bash che stai eseguendo, e pubblica alcuni piccoli esempi di input che riproducono il tuo problema.