2016-04-09 6 views
3

Ich haben eine Protokolldatei, die Daten unten enthalten:Schnitzen Daten aus Protokolldatei

time=1460196536.247325 latency=3:6:7:9:16:(8)ms latency95=11ms latency99=13ms requests=517 option1=0 option2=0 errors=0 throughput=480rps ql=1 rr=0.00% cr=0.00% accRequests=101468 accOption1=0 accOption2=0 accLatency=2:6:7:8:3998:(31)ms accLatency95=11ms accLatency99=649ms accOpenQueuing=1664 accErrors=278 

Ich versuche bashscript zu schreiben, wo ich versuche, diese Werte für jede Zeile in der Protokolldatei zu schnitzen und zu einem schreiben zweite Datei:

  • Zeit (in Ortszeit konvertiert GMT + 2)
  • latency99
  • Anfragen
  • Fehler

gewünschte Ausgabe in der zweiten Datei:

time latency99 requests errors 

12:08:56 13   517   0 

ist der einfachste Weg regex für diesen Einsatz?

Antwort

3

Hier ist eine Bash-Lösung für Version 4 und höher, ein assoziatives Array mit:

#!/bin/bash 
# Assoc array to hold data. 
declare -A data 
# Log file (the input file). 
logfile=$1 
# Output file. 
output_file=$2 

# Print column names for required values. 
printf '%-20s %-10s %-10s %-10s\n' time latency99 requests errors > "$output_file" 
# Iterate over each line in $logfile 
while read -ra arr; do 
    # Insert keys and values into 'data' array. 
    for i in "${arr[@]}"; do 
     data["${i%=*}"]="${i#*=}" 
    done 
    # Convert time to GMT+2 
    gmt2_time=$(TZ=GMT+2 date -d "@${data[time]}" '+%T') 
    # Print results to stdout. 
    printf '%-20s %-10s %-10s %-10s\n' "$gmt2_time" "${data[latency99]%ms}" "${data[requests]}" "${data[errors]}" >> "$output_file" 
done < "$logfile" 

Wie Sie sehen können, wird das Skript zwei Argumente akzeptiert. Der erste ist der Dateiname der Logdatei und der zweite ist die Ausgabedatei, in die geparste Daten Zeile für Zeile für jede Zeile in der Logdatei eingefügt werden.

Bitte beachten Sie, dass ich GMT+2 als Wert für die TZ Variable verwendet habe. Verwenden Sie stattdessen den exakten Bereich als Wert. Wie zum Beispiel TZ="Europe/Berlin". Sie können das Tool verwenden, um den korrekten Zeichenfolgenwert Ihres Bereichs zu ermitteln.

Um es zu testen, habe ich die folgende Protokolldatei, 3 verschiedene Reihen von Eingangs enthalten:

time=1260196536.242325 latency=3:6:7:9:16:(8)ms latency95=11ms latency99=10ms requests=100 option1=0 option2=0 errors=1 throughput=480rps ql=1 rr=0.00% cr=0.00% accRequests=101468 accOption1=0 accOption2=0 accLatency=2:6:7:8:3998:(31)ms accLatency95=11ms accLatency99=649ms accOpenQueuing=1664 accErrors=278 
time=1460246536.244325 latency=3:6:7:9:16:(8)ms latency95=11ms latency99=20ms requests=200 option1=0 option2=0 errors=2 throughput=480rps ql=1 rr=0.00% cr=0.00% accRequests=101468 accOption1=0 accOption2=0 accLatency=2:6:7:8:3998:(31)ms accLatency95=11ms accLatency99=649ms accOpenQueuing=1664 accErrors=278 
time=1260236536.147325 latency=3:6:7:9:16:(8)ms latency95=11ms latency99=30ms requests=300 option1=0 option2=0 errors=3 throughput=480rps ql=1 rr=0.00% cr=0.00% accRequests=101468 accOption1=0 accOption2=0 accLatency=2:6:7:8:3998:(31)ms accLatency95=11ms accLatency99=649ms accOpenQueuing=1664 accErrors=278 

der den Test (Skriptname sof ist ) laufen lassen:

$ ./sof logfile parsed_logfile 
$ cat parsed_logfile 
time     latency99 requests errors  
12:35:36    10   100  1   
22:02:16    20   200  2   
23:42:16    30   300  3 

EDIT:

Nach OP Anfrage wie in den Kommentaren gesehen werden kann, und wie diskutiert weiter im Chat, herausgegeben ich das Skript auf die folgenden Funktionen umfasst:

  • entfernen ms Suffix von latency99 ‚s-Wert.
  • Eingabe aus einer Protokolldatei lesen, Zeile für Zeile analysieren und Ergebnisse an eine ausgewählte Datei ausgeben.
  • Spaltennamen nur in die erste Zeile der Ausgabe einschließen.
  • Konvertieren Sie den Zeitwert in GMT + 2.
+0

Aus irgendeinem Grund, den ich dieses: (Bash Version 4.2.25) './test.sh Spalte: Zeile zu lang Zeit latency99 Anfragen errors' – user3580316

+1

Ich verstehe. Es ist die Grenze der Länge der Eingabezeile in Bytes, definiert durch 'column'. Ich habe meine Antwort so bearbeitet, dass ich nur 'printf' verwende. –

+0

Wie entferne ich die 'ms' nach 13? Ich muss eine Protokolldatei definieren, die es zeilenweise liest und dann die Ausgabe in eine andere Datei schreibt? – user3580316

2

Hier ist ein awk-Skript für Sie. Sagen wir die Logdatei ist mc.log und das Skript wird als mc.awk gespeichert, Sie würden es wie folgt ausführen: awk -f mc.awk mc.log mit GNU awk.

mc. awk:

BEGIN{ 
     OFS="\t" 
     # some "" to align header and values in output 
     print "time", "", "latency99", "requests", "errors" 
    } 

    function getVal(str) { 
     # strip leading "key=" and trailing "ms" from str 
     gsub(/^.*=/, "", str) 
     gsub(/ms$/, "", str) 
     return str 
    } 

    function fmtTime(timeStamp){ 
     val=getVal(timeStamp) 
     return strftime("%H:%M:%S", val) 
    } 

    { 
     # some "" to align header and values in output 
     print fmtTime($1), getVal($4), "", getVal($5), "", getVal($8) 
    } 
+0

Ich bekomme 'awk: mc.awk: Zeile 24: Funktion strftime nie definiert ' – user3580316

+0

@ user3580316 Ich verwende:' awk --version': GNU Awk 4.0.1. Was für eine awk verwendest du? Wenn Sie stattdessen "val" zurückgeben, erhalten Sie den unformatierten Zeitstempel. –

+0

@ user3580316 Welches Betriebssystem und welche awk Version verwendest du, vielleicht kannst du GNU awk als gawk installieren und du kannst den folgenden Befehl ausführen: 'gawk -f mc.awk mc.log' stattdessen. –

0

Hier ist eine awk Version (nicht GNU). das Datum Umwandlung würde einen Anruf an ein externes Programm benötigen:

#!/usr/bin/awk -f 

BEGIN { 
    FS="([[:alpha:]]+)?[[:blank:]]*[[:alnum:]]+=" 
    OFS="\t" 
    print "time", "latency99", "requests", "errors" 
} 
{ 
    print $2, $5, $6, $9 
} 
Verwandte Themen