码迷,mamicode.com
首页 > 系统相关 > 详细

shell在大文件日志中按照时间段快速搜索日志

时间:2016-05-07 07:36:39      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:

问题描述:

在大流量线上服务中,日志系统会产生数量庞大的日志,动辄就是几十G。在如此之大的文件中快速搜索日志是运维人员经常遇见的问题。我们经常遇见的问题是查询一段时间内的某些条日志。比如,今天有一个访问失败了,大约是在上午9点,把这条日志找出来,然后查找失败原因。

技术分享

常见处理方式及缺点:

1.如果文件比较小,100m以内使用grep、awk或者sed进行逐条匹配比较方便,但是文件非常大时,其查找效率是非常低的,运行时间长达几十分钟甚至上小时。

2.使用hadoop大数据处理,查询速度快,效率高。但是需要我们搭一套hadoop环境,需要巨大的计算量。感觉就是杀鸡焉用牛刀。

3.按照时间手动查找,使用tail -c size filename 命令 提取出一段日志,看看时间是否符合条件。如果不符合就调整size参数直到找到9点之前的时间段,然后从这里开始查起,使用grep、awk或者sed进行逐条匹配,直到找到目标日志然后ctrl+c停止,这样确实能省下很多时间,也是我以前经常用的一种方式。

解决方案:

很显然,手动查找不是一个程序员的理想解决方案,那么能不能写一个脚本自动按照时间段查找超大日志呢?常用的命令如,cat、head、tail、grep、more、less、sed、awk貌似都不能提供有效的方案。下面就是Blog介绍的方法。

下面就是我的脚本,姑且称它为探针法:

技术分享
#!/bin/bash
#读入文件名
file_name=$1
#读入查询起始时间
start=$2
#读取文件大小
file_size=$(stat --format=%s $file_name)
#设置探针步长,一般为文件大小的百分之一到千分之一
step=500000000
#如果文件大小小于步长,则size为文件大小,否则size为步长
[ $file_size -lt $step ] && size=$file_size || size=$step
#初始化探针时间
test_time="00:00:00"
#循环检测,直到探针时间大于查询时间,停止
while [[ ${test_time} < ${start} ]]
do size=$(($size+$step))
    test_time=$(dd if=$file_name skip=$(($size/10000)) ibs=10000 count=1 2>/dev/null | sed -n "2p" | awk {print $3})
done
#读取此时的查询size,使用tail -c命令即从目标时间开始查日志。
tail -c $(($file_size-$size+$step)) $file_name
技术分享

执行sh find.sh filename.log 09:00:00 , 然后再使用grep等命令过滤。

解释一下,这里主要用到了dd命令:拷贝一个文件,并按照参数对其处理转换。

具体的介绍可以查看相关文档,例如,http://blog.chinaunix.net/uid-24958038-id-3416169.html

技术分享

这里利用dd命令从超大文件中复制出一小块,提取出时间,也就是test_time,判断test_time是否符合条件,不符合就使size增加一个步长然后继续提取时间,直到符合条件。因为dd命令有skip选项,可以直接跳过指定大小部分截取到一段,其效率是非常高的,循环500次耗时大于1s,也就是说探针测试500次的时间是1s左右。

dd命令截取出一段日志后使用sed取出完整的一行,然后用awk取出时间戳。

 注意,设定时间为09:00:00,查询结果并不是严格从09:00:00开始的,一般会往前一点,这里受step参数影响。step越小越精确,而探针尝试次数越多。

 

原创,转发请注明。 By LZJing

shell在大文件日志中按照时间段快速搜索日志

标签:

原文地址:http://blog.csdn.net/a568078283/article/details/51331213

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!