日志分析查看——grep,sed,sort,awk运用
Posted teamlet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日志分析查看——grep,sed,sort,awk运用相关的知识,希望对你有一定的参考价值。
概述
我们日常应用中都离不开日志。可以说日志是我们在排查问题的一个重要依据。但是日志并不是写了就好了,当你想查看日志的时候,你会发现线上日志堆积的长度已经超越了你一行行浏览的耐性的极限了。于是,很有必要通过一些手段来高效地辅助你来快速的从日志中找到你要找的问题。本文通过一个从项目中衍生出来的例子从查找日志,筛选日志和统计日志3个方面层层递进来简述日志文件查看中一些有用的手段。(注:在linux环境下)
目录
例子背景:
后台跑一个定时任务,对指定时间段的订单数据表中的每一条记录进行以此任务处理。在日志中输出:
1.订单id
2.订单处理状态
3.日志类别
准备工具:sort, tail, less, uniqu,grep,sed,awk
示例日志:demo.log
[plain] view plain copy- 2011-08-23 19:57:00,610 [] INFO bo.CommodityCerOrderBO - =====>属性订正任务执行开始|每页读取100条数据
- 2011-08-23 19:57:05,012 [] INFO bo.CommodityCerOrderBO - 当前正在处理页数:1
- 2011-08-23 19:57:30,688 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids不含0跳过
- 2011-08-23 19:57:30,709 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100104
- 2011-08-23 19:57:31,721 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100105
- 2011-08-23 19:57:32,727 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100107
- 2011-08-23 19:57:32,782 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids成功保存为0|100104|0|100105|100107
- 2011-08-23 19:57:32,782 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:attr_ids不含0跳过
- 2011-08-23 19:57:32,805 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100104
- 2011-08-23 19:57:33,828 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100107
- 2011-08-23 19:57:33,838 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:46
- 2011-08-23 19:57:34,850 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100106
- 2011-08-23 19:57:35,860 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100105
- 2011-08-23 19:57:36,871 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:3
- 2011-08-23 19:57:36,884 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:3
- 2011-08-23 19:57:36,891 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:attr_ids成功保存为6|100104|0|0|100107|46|100106|100105|3|3
- 2011-08-23 19:57:36,891 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:attr_ids不含0跳过
- 2011-08-23 19:57:36,928 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:3
- 2011-08-23 19:57:36,942 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100104
- 2011-08-23 19:57:36,955 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100105
- 2011-08-23 19:57:36,969 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100107
- 2011-08-23 19:57:36,980 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:46
- 2011-08-23 19:57:36,992 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100106
- 2011-08-23 19:57:37,011 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:3
0.一些最基础的日志查看命令
最简单的日志查看命令就是浏览日志文件了,一般会从有限浏览文件末尾的
[plain] view plain copy- tail -400f demo.log #监控最后400行日志文件的变化 等价与 tail -n 400 -f (-f参数是实时)
- less demo.log #查看日志文件,支持上下滚屏,查找功能
- uniq -c demo.log #标记该行重复的数量,不重复值为1
以上命令具体使用详见本机man手册
1.查找关键日志记录 grep
浏览了日志文件后你会发现,日志文件成千上万行,怎么能找到我要找的内容呢。这时候,就可已用grep来进行日志的关键行提取了。
grep 简单使用
规则:grep [选项]...模式 [文件]... (模式是正则表达式)
例子1:
[plain] view plain copy- grep 'INFO' demo.log #在文件demo.log中查找所有包行INFO的行
输出:
2011-08-23 19:57:00,610 [] INFO bo.CommodityCerOrderBO - =====>属性订正任务执行开始|每页读取100条数据
2011-08-23 19:57:05,012 [] INFO bo.CommodityCerOrderBO - 当前正在处理页数:1
2011-08-23 19:57:30,688 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids不含0跳过
...(略)
例子2:
[plain] view plain copy- grep -o 'order-fix.curr_id:\\([0-9]\\+\\)' demo.log #-o选项只提取order-fix.curr_id:xxx的内容(而不是一整行),并输出到屏幕上
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10226
...(略)
例子3:
[plain] view plain copy- grep -c 'ERROR' demo.log #输出文件demo.log中查找所有包行ERROR的行的数量
输出:17
例子4:
- grep -v 'ERROR' demo.log #查找不含"ERROR"的行
grep 用法小结(转自网络图片):请点击直接查看大图
详细用法请man之
2.精简日志内容 sed
从n多行的日志文件中提取到一定数量的行后,可能你还会觉得有些功能不够,比如你每行并不需要有哪个类抛出的描述,比如你不需要日志时间,或者要把时间格式换个形式展示等等,这时候你就可以通过sed的替换命令来进行对日志文件提取具体内容了。
如果把grep比作过滤器,那sed就是个修改器了。
sed简单用法:
[plain] view plain copy- sed [-n][-e] '命令' 文件 #-n选项是默认不输出信息,除非使用了p命令或者是s命令的p标志符;-e是表明空格后面接的是一个命令
- sed [-n] -f 脚本 文件 #这个用法是把命令写在脚本里
»'命令'的格式: [地址1[,地址2]][!] 指令 [参数]
» 地址的格式:用行号标识(1 表明匹配第一行),或者用正则表达式匹配('^INFO'表明该地址匹配以INFO打头的行)
» 指令的例子:p打印指令,s替换指令,d删除指令等等(以下表格摘自abs的sed小册子):
操作符 | 名字 | 效果 |
---|---|---|
[地址范围]/p | 打印 | 打印[指定的地址范围] |
[地址范围]/d | 删除 | 删除[指定的地址范围] |
s/pattern1/pattern2/ | 替换 | 将指定行中, 将第一个匹配到的pattern1, 替换为pattern2. |
[地址范围]/s/pattern1/pattern2/ | 替换 | 在地址范围指定的每一行中, 将第一个匹配到的pattern1, 替换为pattern2. |
[地址范围]/y/pattern1/pattern2/ | transform | 在地址范围指定的每一行中, 将pattern1中的每个匹配到pattern2的字符都使用pattern2的相应字符作替换. (等价于tr命令) |
g | 全局 | 在每个匹配的输入行中, 将每个模式匹配都作相应的操作. (译者注: 不只局限于第一个匹配) |
例1:(摘自abs的sed小册子)
8d | 删除输入的第8行. |
/^$/d | 删除所有空行. |
1,/^$/d | 从输入的开头一直删除到第1个空行(第一个空行也删除掉). |
/Jones/p | 只打印那些包含"Jones"的行(使用-n选项). |
s/Windows/Linux/ | 在每个输入行中, 将第一个出现的"Windows"实例替换为"Linux". |
s/BSOD/stability/g | 在每个输入行中, 将所有"BSOD"都替换为"stability". |
s/ *$// | 删除掉每行结尾的所有空格. |
s/00*/0/g | 将所有连续出现的0都压缩成单个的0. |
/GUI/d | 删除掉所有包含"GUI"的行. |
s/GUI//g | 将所有"GUI"都删除掉, 并保持剩余部分的完整性. |
看完基本用法,让我们结合demo.log来具体应用下:
例2:输出demo.log中的某个日期中的ERROR的行
来具体应用下:
- sed -n '/^2011-08-23.*ERROR/p' demolog.log
2011-08-23 19:57:30,709 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100104
2011-08-23 19:57:31,721 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100105
2011-08-23 19:57:32,727 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100107
例3:提取demo.log中的日期,日志级别,订单id和状态。
[plain] view plain copy
- sed -f demo.sed2 demo.log
- #n #这一行用法和命令中的-n一样意思,就是默认不输出
- #demo.sed2
- #下面的一行是替换指令,就是把19位长的日期和INFO/ERROR,id,和后面的一截提取出来,然后用@分割符把这4个字段重新按顺序组合
- s/^\\([-\\: 0-9]\\19\\\\).*\\(INFO\\|ERROR\\) .*order-fix.curr_id:\\([0-9]\\+\\),\\(.*$\\)/\\1@\\3@\\2@\\4/p
输出:
2011-08-23 19:57:30@10117@INFO@status:attr_ids不含0跳过2011-08-23 19:57:30@10117@ERROR@status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100104
2011-08-23 19:57:31@10117@ERROR@status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100105
2011-08-23 19:57:32@10117@ERROR@status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100107
2011-08-23 19:57:32@10117@INFO@status:attr_ids成功保存为0|100104|0|100105|100107
...略
sed详细用法可以参考《sed 与 awk》(第二版), 或者man之
或者点击下面这个参考链接http://www.reddragonfly.org/abscn/x17814.html
3.对记录进行排序 sort
经过了日志文件的精炼后,我们可能不想对日志进行时间排序,这时候我们就可以用sort进行排序。
基本使用
sort [options] [file...]
对于demo.log,经过了上面的sed提取后,我希望先用id进行排序,然后再用日志级别倒序进行排序,最后才是日期排序
[plain] view plain copy- #排序功能 -t表示用@作为分割符,-k表示用分割出来的第几个域排序(不要漏掉后面的,2/,3/,1,详细意思看下面的参考链接,这里不做详述)
- sed -f test.sed demolog.log | sort -t@ -k2,2n -k3,3r -k1,1 #n为按数字排序,r为倒序
2011-08-23 19:57:30@10117@INFO@status:attr_ids不含0跳过 以上是关于日志分析查看——grep,sed,sort,awk运用的主要内容,如果未能解决你的问题,请参考以下文章 linux生产文本处理掌握这些就够了:awk,gawk,sed,grep,sort linux生产文本处理掌握这些就够了:awk,gawk,sed,grep,sort
2011-08-23 19:57:32@10117@INFO@status:attr_ids成功保存为0|100104|0|100105|100107
2011-08-23 19:57:30@10117@ERROR@status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100104
2011-08-23 19:57:31@10117@ERROR@status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100105
2011-08-23 19:57:32@10117@ERROR@status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100107
2011-08-23 19:57:36@10222@INFO@status:attr_ids不含0跳过
2011-08-23 19:57:36@10222@ERROR@status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100104
2011-08-23 19:57:36@10222@ERROR@status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100105
2011-08-23 19:57:36@10222@ERROR@status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100106
2011-08-23 19:57:36@10222@ERROR@status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100107
2011-08-23 19:57:36@10222@ERROR@status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:3
2011-08-23 19:57:36@10222@ERROR@status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:46
2011-08-23 19:57:37@10222@ERROR@status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:3
2011-08-23 19:57:32@10226@INFO@status:attr_i