2016-04-09 1 views
3

У меня есть файл журнала, содержащий данные ниже:Carving данные из файла журнала

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 

Я пытаюсь написать bashscript, где я стараюсь, чтобы вырезать эти значения для каждой строки в файле журнала и записать его на второй файл:

  • время (в пересчете на местное время GMT + 2)
  • latency99
  • Спросы
  • ошибки

Желаемая выход во втором файле:

time latency99 requests errors 

12:08:56 13   517   0 

это самый простой способ использовать регулярное выражение для этого?

ответ

3

Вот Bash решение для версии 4 и выше, с помощью ассоциативного массива:

#!/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" 

Как вы можете видеть, сценарий принимает два аргумента. Первый - это имя файла журнала, а второй - это выходной файл, в который будут вставлены анализируемые данные по строкам для каждой строки в файле журнала.

Обратите внимание, что я использовал GMT+2 как значение переменной TZ. Используйте точную область как значение вместо этого. Например, TZ="Europe/Berlin". Возможно, вы захотите использовать инструмент tzselect, чтобы узнать правильное строковое значение вашей области.

Для того чтобы проверить это, я создал следующий лог-файл, содержащий 3 разные строки ввода:

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 

Давайте запустим тест (имя скрипта соф):

$ ./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:

Согласно запросу OP, как видно из комментариев, и, как обсуждалось далее в чате, я редактировал сценарий включает в себя следующие функции:

  • Удалить ms суффикс от значения latency99 «s.
  • Чтение ввода из файла журнала, строка за строкой, анализ и вывод результатов в выбранный файл .
  • Включить имена столбцов только в первой строке вывода.
  • Преобразование значения времени в GMT + 2.
+0

По какой-то причине, я получаю это: (Bash версии 4.2.25) './test.sh колонка: линия слишком долго времени latency99 запросы errors' – user3580316

+1

Я вижу. Это предел длины входной строки в байтах, определяемой 'column'. Я отредактировал свой ответ, чтобы использовать только 'printf'. –

+0

Как удалить «мс» после 13? Мне нужно определить файл журнала, который он читает за строкой, а затем записывает вывод в другой файл? – user3580316

2

Это awk-скрипт для вас. Скажем, файл журнала mc.log, и скрипт сохраняется как mc.awk, вы запускаете его следующим образом: awk -f mc.awk mc.log с 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

Я получаю 'awk: mc.awk: строка 24: функция strftime never defined' – user3580316

+0

@ user3580316 Я использую:' awk -version': GNU Awk 4.0.1. Какой awk вы используете? Если вы просто вернете val', вы получите неформатированную метку времени. –

+0

@ user3580316 В какой операционной системе и awk-версии вы используете, возможно, GNU awk устанавливается как gawk, и вы можете запустить следующую команду: 'gawk -f mc.awk mc.log'. –

0

Вот awk версия (не GNU). Преобразование даты потребует вызова внешней программы:

#!/usr/bin/awk -f 

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