从日志文件中雕刻数据

时间:2016-04-09 10:37:37

标签: bash shell logging extract multiple-columns

我有一个包含以下数据的日志文件:

 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 

这是使用正则表达式的最简单方法吗?

2 个答案:

答案 0 :(得分:2)

这是使用关联数组的版本4及更高版本的Bash解决方案:

#!/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 ):

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

编辑:

根据OP请求可以在评论中看到,并且如聊天中进一步讨论的那样,我编辑了脚本以包含以下功能:

  • ms的值中删除latency99后缀。
  • 从日志文件中读取输入,逐行,解析并将结果输出到a 选定的文件。
  • 仅在输出的第一行包含列名称。
  • 将时间值转换为GMT + 2.

答案 1 :(得分:0)

这是awk版本(不是GNU)。转换日期需要调用外部程序:

#!/usr/bin/awk -f

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