昨天同事遇到排查问题困难,异常日志没有收集在elk上,因此我推荐他根据时间进行抛出的日志定位,发现日志筛选过久,目前没有发现有什么快速定位的命令,故而使用python2进行日志定位
py2_javalogsearch.py
#!/usr/bin/python2
#coding:utf-8
#修改自https://www.cnblogs.com/liaojiafa/p/5184750.html
#linux上一般都是默认Python2
import os
import time
import sys
class SearchLog(object):
def __init__(self, file_name):
self.fp = open(file_name)
self.fp.seek(0, os.SEEK_END)
self.size = self.fp.tell()
self.fp.seek(0, os.SEEK_SET)
#匹配规则
def Search_cmp(self, timestamp, line):
return cmp(timestamp,line[0:len(timestamp)])
#定位行首
def Search_LineHead(self):#定义一个匹配每行开头的方法
while self.fp.tell() > 0:
self.fp.seek(-1, os.SEEK_CUR)#把文件内容的指针在当前位置往前挪一位
val = self.fp.read(1)# 读取该指针位置的内容
if val == '\n':#匹配该指针内容的值是否等于换行符,等于就跳出循环
break
self.fp.seek(-1, os.SEEK_CUR)#不等于就就继续往前挪一位查找
#二分法查找行
def Search_TimeStamp(self, timestamp, start_p = 0):
fp_start = start_p
fp_end = self.size
while fp_start < fp_end:#判断指针开始位置是否小于结束位置
mid = fp_start + (fp_end-fp_start)/2#找出中间值(利用二分法)
self.fp.seek(mid, os.SEEK_SET)#通过seek定位到中间值
self.Search_LineHead()
line = self.fp.readline()
val = self.Search_cmp(timestamp, line)#调用该方法能够匹配时间戳,返回值为0那么就说明找到了时间戳
if val == 0:
return True
elif val == 1:
fp_start = self.fp.tell()#如果等于1,说明当前内容的时间戳比输入的时间戳大
else:
fp_end = mid#如果等于其他的,说明当前内容的时间戳比输入的时间戳小,
#找开始时间
def Search_FirstStamp(self, timestamp, start_p = 0):
first_point = -1
val = self.Search_TimeStamp(timestamp, start_p)
if val == True:
point = self.fp.tell()#这里的逻辑是这样的==>
while point > 0:#如果search_timestamp这个方法匹配到了时间戳,并且指针恒大于0的话,指针就在当前位置往前挪,直到匹配到换行符,再把这行通过readlie()方法整行独取出来。
self.fp.seek(-1, os.SEEK_CUR)#此时再去匹配每行的开头是否等于时间戳,如果等于的话,那么就把指针从文件内容开头移动到匹配到时间戳的这行,标记这行为要查找的时间戳出现的第一行。
self.Search_LineHead()
point = self.fp.tell()
line = self.fp.readline()
# print line
if self.Search_cmp(timestamp,line) <=0:#继续往上搜索
self.fp.seek(point, os.SEEK_SET)
continue
first_point = self.fp.tell()
break
return first_point
def Search_EndStamp(self, timestamp, start_p = 0):
last_point = -1
val = self.Search_TimeStamp(timestamp, start_p)
if val == True:#道理同上,不过这个的就反转过来,用来查找要查找的时间戳的最后一行。
last_point = self.fp.tell()
while last_point < self.size:
line = self.fp.readline()
if self.Search_cmp(timestamp,line) >=0: #往下搜索
last_point = self.fp.tell()
continue
# print line
self.fp.seek(last_point, os.SEEK_SET)
break
return last_point
#导出中间行
def Search_Dump(self, s_p, e_p):#把查找到的内容写入日志
self.fp.seek(s_p, os.SEEK_SET)
dumpname="lastSearch.log"
f_log=open(dumpname,'wb')
while self.fp.tell() < e_p:
print self.fp.readline(),
f_log.write(self.fp.readline())
f_log.close()
print "dump in "+dumpname
def Search_DeInit(self):
self.fp.close()
if __name__ == '__main__':
if len(sys.argv)!=4:
print '用法:\n\t本脚本 开始时间 结束时间 日志路径\n例子:\n\tpython '+sys.argv[0]+' "2021-04-14 15:26" "2021-04-14 15:29" /opt/logs/*/log/all.log'
else:
time_s = time.time()
obj = SearchLog(sys.argv[3])
s_point = obj.Search_FirstStamp(sys.argv[1])
if s_point > -1:
e_point = obj.Search_EndStamp(sys.argv[2], s_point)
if s_point > -1:
print s_point , e_point
obj.Search_Dump(s_point, e_point)
else:
print "not find"
print "use time",time.time()-time_s,"s"
obj.Search_DeInit()