一、需求描述

最近接到一个分析异常日志的需求,因为日志内容比较繁杂庞大,因此需要对日志关键异常信息进行过滤,通过awk即可实现。

二、日志格式

日志格式如下,可以主要需要获取的是 异常报错行异常类型

centos rsyslog 日志过滤 linux过滤日志error_centos rsyslog 日志过滤

三、关键信息过滤实现

$0——获取整行
~/ERROR/——匹配带ERROR的行

print $0——输出获取到的整行
(注意print会自动换行,printf不会自动换行)

getline——进入下一行
print $0——输出获取到的整行,实际上就是为了输出下一行

print "\n"——输出换行,使输出更美观。
(如果需要继续对数据进行处理建议使用其他符号划分,比如“-------------”)
awk '$0~/ERROR/{print $0; getline; print $0;print"\n"}'   error.log

执行结果如下

centos rsyslog 日志过滤 linux过滤日志error_linux_02


如果对于错误提示行,我不想要时间这些无关列,只想要[ERROR]后的列怎么办

$0是获取整行
~/ERROR/——匹配带ERROR的行
print $0——输出获取到的整行
NF——一条记录的字段的数目 

{for(i=5;i<=NF;i++) printf $i" ";}——输出ERROR后的所有列,以空格分割
(注意print会自动换行,printf不会自动换行)

getline——进入下一行
print $0——输出获取到的整行,实际上就是为了输出下一行

print "\n"——输出换行,使输出更美观。
(如果需要继续对数据进行处理建议使用其他符号划分,比如“-------------”)
awk '$0~/ERROR/{for(i=5;i<=NF;i++) printf $i" ";printf"\n"; getline; print $0;print"\n"}'   error.log

可以看到,输出结果少了很多不需要的信息。

centos rsyslog 日志过滤 linux过滤日志error_shell_03

四、关键信息去重并统计

因为最终目的是对异常进行分类和统计,因此这里用=====进行字段分割,同时不再使用print "/n"多输出一行换行,而是使用printf "\n"在这行数据输出完毕后换行,最终每一行就是异常报错点——异常类型的格式,将输出进行去重并统计即可。
如果下一行中带有变量,比如请求用户的id等等,可以substring($0,m,n)来截取字符串。

awk '$0~/ERROR/{for(i=6;i<=NF;i++) printf $i" ";printf"====="; getline; print $0;}' error.log |sort|uniq -c | sort -n -r

去重结果如下图所示:

centos rsyslog 日志过滤 linux过滤日志error_linux_04

Tips:如果awk提示run for this one很有可能是printf输出的内容带有%导致的,通过sed命令先去掉文件中的%即可。

sed -i 's/%//g' 1.log

五、调整后实际应用的Shell脚本及效果

脚本不通用,只提供参考
将脚本放在待分类日志同级目录,然后脚本执行完毕后会在当前目录下新建一个叫statistic的目录,该目录中统计结果文件名 同 原日志文件名。

#!/bin/bash

# 获取当前目录下所有文件名
dir="./"
files=$(ls $dir | grep 'log$')

# 创建用于存储统计后文件的文件夹
mkdir -p ./statistic

# 遍历文件
for file in $files
do
# 如果是log后缀的文件才进行awk操作
    echo "正在对$file文件进行sed及awk操作"

    # 去除对printf的影响
    sed -i 's/%//g' $dir/$file
    # 执行awk命令
    # if语句判断第六列是否含有:,即我所需要的报错位置信息,若无则将前一列加上即可解决此问题
    # substr截断字符串获取关键信息
    # getline获取下一行
    # uniq -c 去重并在行左侧显示重复次数
    # sort -n -r将数字字符按照数字而不是字符来排序
    # > 将结果输出到某文件
    #  因为有些行不存在异常类型输出,因此这里判断下一行是否含有异常报错位置行的某一特殊标识
    awk '$0~/\[ERROR\]/{if(!match($6,":")) printf $5;printf substr($6,1,70);printf"====="; getline; if(!match($0,"QTraceId") && !match($0,"ERROR")) printf substr($0,1,60); printf "\n" }' $dir/$file |sort|uniq -c | sort -n -r > $dir/statistic/$file
done

echo "执行统计分类完毕,结果在当前目录/statistic文件夹下"

效果如下,最终以频次 异常报错位置=====异常类型的格式输出

centos rsyslog 日志过滤 linux过滤日志error_shell_05