概述 html
咱们平常应用中都离不开日志。能够说日志是咱们在排查问题的一个重要依据。可是日志并非写了就行了,当你想查看日志的时候,你会发现线上日志堆积的长度已经超越了你一行行浏览的耐性的极限了。因而,颇有必要经过一些手段来高效地辅助你来快速的从日志中找到你要找的问题。本文经过一个从项目中衍生出来的例子从查找日志,筛选日志和统计日志3个方面层层递进来简述日志文件查看中一些有用的手段。(注:在linux环境下) java
目录 linux
0.查找关键日志grep 正则表达式
1.查找关键日志grep shell
2.精简日志内容 sed bash
4.统计日志相关记录数 awk less
5.日志规范化 ssh
6.一些容易遇到的问题 函数
例子背景:
后台跑一个定时任务,对指定时间段的订单数据表中的每一条记录进行以此任务处理。在日志中输出:
1.订单id
2.订单处理状态
3.日志类别
准备工具:sort, tail, less, uniqu,grep,sed,awk
示例日志:demo.log
0.一些最基础的日志查看命令
最简单的日志查看命令就是浏览日志文件了,通常会从有限浏览文件末尾的
以上命令具体使用详见本机man手册
1.查找关键日志记录 grep
浏览了日志文件后你会发现,日志文件成千上万行,怎么能找到我要找的内容呢。这时候,就可已用grep来进行日志的关键行提取了。
grep 简单使用
规则:grep [选项]...模式 [文件]... (模式是正则表达式)
例子1:
输出:
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:
例子3:
输出:17
例子4:
grep 用法小结(转自网络图片):请点击直接查看大图
详细用法请man之
2.精简日志内容 sed
从n多行的日志文件中提取到必定数量的行后,可能你还会以为有些功能不够,好比你每行并不须要有哪一个类抛出的描述,好比你不须要日志时间,或者要把时间格式换个形式展现等等,这时候你就能够经过sed的替换命令来进行对日志文件提取具体内容了。
若是把grep比做过滤器,那sed就是个修改器了。
sed简单用法:
»'命令'的格式: [地址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的行
来具体应用下:
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和状态。
输出:
2011-08-23 19:57:30@10117@INFO@status:attr_ids不含0跳过
sed详细用法能够参考《sed 与 awk》(第二版), 或者man之
或者点击下面这个参考连接http://www.reddragonfly.org/abscn/x17814.html
3.对记录进行排序 sort
通过了日志文件的精炼后,咱们可能不想对日志进行时间排序,这时候咱们就能够用sort进行排序。
基本使用
sort [options] [file...]
对于demo.log,通过了上面的sed提取后,我但愿先用id进行排序,而后再用日志级别倒序进行排序,最后才是日期排序
2011-08-23 19:57:30@10117@INFO@status:attr_ids不含0跳过
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_ids不含0跳过
2011-08-23 19:57:36@10226@INFO@status:attr_ids成功保存为6|100104|0|0|100107|46|100106|100105|3|3
2011-08-23 19:57:32@10226@ERROR@status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:100104
2011-08-23 19:57:33@10226@ERROR@status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:100107
2011-08-23 19:57:33@10226@ERROR@status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:46
2011-08-23 19:57:34@10226@ERROR@status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:100106
2011-08-23 19:57:35@10226@ERROR@status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:100105
2011-08-23 19:57:36@10226@ERROR@status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:3
2011-08-23 19:57:36@10226@ERROR@status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:3
详尽手册http://ss64.com/bash/sort.html
4.统计日志相关记录数 awk
如今日志已经比较清晰了,可是若是我想对不一样日志进行统计怎么办,好比我要统计全部ERROR的日志记录书,或者要统计每一个订单有多少个ERROR?这就须要咱们的awk帮忙了。
awk简单使用:
和sed同样,awk也支持2中方式调用,一种是把awk脚本直接在命令行写入,第二种是把awk写在文件中在命令行中调用。
awk处理方式也与sed相似,对文件中的每个输入行进行处理,每一个处理首先判断是不是模式中匹配的行,是的话就具体执行相应的语句。
不一样的是,awk侧重与对每一行的列进行处理,而且,awk脚本和c语言相似也拥有变量,条件判断,循环等复杂语句,因此这里只能简单介绍一下基本应用,详细的请查看后面给出的相关连接。并且,awk在处理全部行前和处理完行后各有BEGIN和END语句作预处理和后置处理。
例子1:打印日志中的第2,3列
例子2. 统计日志中INFO,ERROR出现的总数,以及总记录数
输出:
order total count:22
INFO count:5 ERROR count:17
例子3. 对指定时间范围内的日志进行统计,包括输出INFO,ERROR总数,记录总数,每一个订单记录分类统计
下面的例子综合了前面sed和sort
id:10117:
2011-08-23 19:57:32 INFO status:attr_ids成功保存为0|100104|0|100105|100107
2011-08-23 19:57:32 ERROR status:添加属性id,但因为认证分类参数有误默认取匹配属性名称的第一个属性id:100107
id:10226:
2011-08-23 19:57:32 INFO status:attr_ids不含0跳过
2011-08-23 19:57:32 ERROR status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:100104
2011-08-23 19:57:33 ERROR status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:100107
2011-08-23 19:57:33 ERROR status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:46
2011-08-23 19:57:34 ERROR status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:100106
2011-08-23 19:57:35 ERROR status:添加属性id,但因为没有属性在该分类下默认取匹配属性名称的第一个属性id:100105
#这个例子只是举例说明awk的统计用法,实际运用中可能会统计超时的次数,页面访问次数等。
awk相关资料:
《sed 与 awk》(第二版)
补充:
其余实践时例子:
1. 在本地分支把代码修改从一个分支复制到另外一个分支(例子的b1022st.txt是一个记录了文件新增或修改的变化的文件路径名)
2.内置函数 http://www.cnblogs.com/chengmo/archive/2010/10/08/1845913.html
3.内建变量 http://www.linuxsong.org/2010/09/awk-built-in-variable/
4.shell变量传递 http://www.51testing.com/?uid-225738-action-viewspace-itemid-246383
5.awk统计某个开始-结束范围内的关键字累加总数:
5.日志规范化
从前面能够看出,日志文件为了要让后续工具可以对里面的内容进行提取和处理,就必需要让日志文件规范的输出。
我的想到有几个点能够规范:
1.记录日志时候能够写入一些特殊的文本语句,一遍与工具的检索和处理。
2.记录日志最好不要用中文,由于在不一样语言环境下对日志的处理可能由于编码不一样致使无法处理日志。
后面再贴下淘宝中找到的一些打印日志的建议:
6.一些容易遇到的问题
a.处理中文出现乱码
这个主要是由于你的linux locale的配置,与编辑文件的语言环境,还有你登陆ssh客户端的编码规则有关,因此最好仍是不用中文记录日志。
b.正则表达式不一样工具的区别
这个主要是由于不一样工具的正则表达式定义的元字符不一样,网上有总结的,可点击正则迷雾参考
OO后记:
目前只是简单介绍了grep,sed,sort,awk的几个简单应用,实际上的日志监控回根据不一样的情景进行不一样的处理。好比须要对调用的耗时进行统计(平均时间或者超时记录),对访问量进行统计,可是基本原理都和本文例子出发点一致。本文一方面是为了记录下学习过程当中积累的东西,另外一方面为了抛砖引玉引发你们对日志记录的关注。