日常筛日志时通过ELK去查询的,但是如果脱离工具如何来做?
通常我们是用ELK去查询过滤的,如果脱离工具,需要运维导出日志,或者直接用grep sed awk 命令搭配正则或者编写shell脚本供运维执行后导出分析
通常查找出错误日志 cat error.log | grep ‘nick’ , 这时候我们还有个需求就是输出当前这个日志的前后几行:
1 | cat error.log | grep -C 5 'nick' 显示file文件里匹配foo字串那行以及上下5行 |
在日常系统维护、问题排查时,经常需要对系统后台日志进行筛选过滤。如果对特定时间段的日志进行筛选,该如何编写Shell脚本(命令)呢?本文给出三种常用的Shell编写方法:grep、gawk和sed。
日志筛选需求描述:从2017年12月22日的日志文件中,统计时间段13:30~18:00之间包含筛选词“open.app”的日志行数。
本系统后台日志格式如下图所示:
从图中可以看出每行日志以“yyyy-MM-dd HH:mm:ss”开头,故要筛选一段时间的日志,就要匹配该日志的时间前缀。
接下来文章分别介绍使用grep、gawk和sed命令,如何进行相关的Shell脚本(命令)的编写。
1grep命令
在日志筛选、搜索中,grep是使用频率较高的命令。对于grep命令来说,如果筛选一段时间的日志,需要进行多条件相并过滤,使用正则表达式进行处理。对于13:30~18:00时间段来说,可以转化为下面表格多个时间相并。
序号 筛选条件 筛选时间段
1 | 1 2017-12-22 13:3 13:30:00~13:39:59 |
命令如下:
1 | grep -E '^2017-12-22 13:3|^2017-12-22 13:4|^2017-12-22 13:5|^2017-12-22 14|^2017-12-22 15|^2017-12-22 16|^2017-12-22 17' 2017-12-22.log.txt | grep 'open.app' | wc -l |
运行结果如下图:
共检索筛选到71314条。
上述命令条件可以使用正则表达式进行缩减,命令如下:
1 | grep -E '^2017-12-22 13:[3,4,5]|^2017-12-22 1[4,5,6,7]' 2017-12-22.log.txt | grep 'open.app' | wc -l |
运行结果如下图所示:
检索筛选到71314条,和上述命令一致。
2gawk命令
gawk命令是功能强大、可编程的Linux命令。使用gawk命令筛选一段时间的日志,其思路是首先截取出每行日志的“yyyy-MM-dd HH:mm:ss”19位时间前缀,然后将该前缀字符串与“2017-12-22 13:30:00”、“2017-12-22 18:00:00”进行比较,不在该范围的日志则丢弃。
命令脚本如下所示:
1 | cat 2017-12-22.log.txt | gawk '{ time = substr($0, 1, 19); if(('2017-12-22 13:30:00' <= time)="" &&="" (time="">< '2017-12-22="" 18:00:00'))=""> { print($0); }}' | grep 'open.app' | wc -l |
运行结果如下图所示:
共检索筛选到71314条。
注:需要注意“2017-12-22 18:00:00”使用的是小于符号,而不是小于等于符号。
3sed命令
sed是一种流编辑器命令,它是文本处理中非常中的工具,能够完美的配合正则表达式使用。使用sed命令选定行的范围语法,既是逗号语法。
命令如下所示:
1 | sed -n '/2017-12-22 13:30:00/,/2017-12-22 18:00:00/p' 2017-12-22.log.txt | grep 'open.app' | wc -l |
运行结果如下图所示:
共检索筛选到71314条。
注:该sed命令含义是选定行范围:从第一行“2017-12-22 13:30:00”开始,到第一行“2017-12-22 18:00:00”结束,包括第一行“2017-12-22 18:00:00”。如果不筛选“open.app”关键字,单纯计数,则sed命令比如上述grep和gawk命令多筛选出一条。
4命令比较
对命令运行时间和命令编写的复杂性进行对比,结果如下表所示:
命令 耗时(秒) 命令复杂性
grep 50 低
gawk 122 高
sed 61 低
从表中可以看出,grep命令运行时间最短;gawk命令运行时间最长,而且命令编写较为复杂。另外sed命令运行时间跟grep相近,但是sed命令对时间段适应性较好。如果时间段扩大,grep命令修改较大,而sed命令修改较小。
筛选15:05–15:10期间的日志
使用sed
1 | sed -n '/Apr 22 15:05/,/Apr 22 15:10/p' syslog > test |
使用grep,与sed提取的行数有差异,待查验。
1 | grep -E '^Apr 22 15:05|^Apr 22 15:06|^Apr 22 15:07|^Apr 22 15:08|^Apr 22 15:09|^Apr 22 15:10' |
使用awk,跟grep提取行数一致,不过会因为分隔符原因,时间戳格式被修改,需要额外辨别,待完善。
1 | awk -F'[:]' '$1 = 15 && $2 >=5 && $2 <= 10 {print $0}' syslog |
linux下使用awk命令按时间段筛选日志
1 | zcat com.log20160529.gz | grep 'dianping_reply'| |
扫描gz压缩文件,从中寻找带有dianping_reply
的行,将改行按照[
进行拆分,然后直接使用if条件进行判断,比较,最终输出想要的结果。
zcat 直接读取压缩文件的内容
grep用来过滤特定字符的行
awk 用来执行命令
split用来切分字符串