本文使用Python2.7解析nginx日志文件,并把nginx的时间转化为时间戳(1970纪元后经过的浮点秒数),并存放到特定文件中。
日志规则描述
Nginx的http日志格式:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" ';
示例如下:
199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085
解决思路
获取所有日志文件
这里使用Python的glob模块来获取所有日志文件。日志文件每天0时进行备份,命名为nginx.log.YYMMDD。
import glob
def readfile(path):
return glob.glob(path + '*')
获取日志中所有行
模块linecache允许从任何文件里得到任何的行,并且使用缓存进行优化,常见的情况是从单个文件读取多行。
import linecache
def readline(path):
return linecache.getlines(path)
解析每一条日志
使用python的re模块解析每一条日志。
正则表达式
ip_regex = r"?P<ip>[\d.]*"
date_regex = r"?P<date>\d+"
month_regex = r"?P<month>\w+"
year_regex = r"?P<year>\d+"
day_time_regex = r"?P<day_time>\S+"
method_regex = r"?P<method>\S+"
request_regex = r"?P<request>\S+"
status_regex = r"?P<status>\d+"
body_bytes_regex = r"?P<body_bytes>\S+"
其中body_bytes捕获非空字符串,而不是数字,因为日志里可能存在该字段值为“-”,即没有请求体。
解析日志
def parse_log(log_line):
"""
解析日志,日志格式: 199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085
"""
log_fmt = r"(%s)\ - \ -\ \[(%s)/(%s)/(%s)\:(%s)\ [\S]+\]\ \"(%s)?[\s]?(%s)?.*?\"\ (%s)\ (%s)\s"
p = re.compile(log_fmt %(ip_regex, date_regex, month_regex, year_regex, day_time_regex, method_regex, request_regex, status_regex, body_bytes_regex),
re.VERBOSE)
return re.search(p, log_line)
时间提取
date、method、request等参数可以采用以下方式进行提取。
matches = parse_log(line)
date = matches.group("date")
month = matches.group("month")
year = matches.group("year")
day_time = matches.group("day_time")
时间转换
使用python的time模块把时间转为时间戳。
def parse_time(date, month, year, log_time):
"""转化为long型时间"""
time_str = '%s%s%s %s' %(year, month, date, log_time)
return time.mktime(time.strptime(time_str, '%Y%b%d %H:%M:%S'))
完整代码
#!/usr/bin/python2
# -*- coding: UTF-8 -*-
import re
import time
import glob
import linecache
ip_regex = r"?P<ip>[\d.]*"
date_regex = r"?P<date>\d+"
month_regex = r"?P<month>\w+"
year_regex = r"?P<year>\d+"
day_time_regex = r"?P<day_time>\S+"
method_regex = r"?P<method>\S+"
request_regex = r"?P<request>\S+"
status_regex = r"?P<status>\d+"
body_bytes_regex = r"?P<body_bytes>\d+"
def read_file(path):
return glob.glob(path)
def read_line(path):
"""读取文件中每一行的内容"""
return linecache.getlines(path)
def write_line(file, str):
file.write(str + "\n")
def parse_log(log_line):
"""
解析日志,日志格式: 199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085
"""
log_fmt = r"(%s)\ - \ -\ \[(%s)/(%s)/(%s)\:(%s)\ [\S]+\]\ \"(%s)?[\s]?(%s)?.*?\"\ (%s)\ (%s)\s"
p = re.compile(log_fmt %(ip_regex, date_regex, month_regex, year_regex, day_time_regex, method_regex, request_regex, status_regex, body_bytes_regex),
re.VERBOSE)
return re.search(p, log_line)
def parse_time(date, month, year, log_time):
"""转化为时间戳,整形,单位秒"""
time_str = '%s%s%s %s' %(year, month, date, log_time)
return int(time.mktime(time.strptime(time_str, '%Y%b%d %H:%M:%S')))
if __name__ == '__main__':
time_file = open("time.log", "a") # 直接打开一个文件用于写,文件指针放在文件的结尾,如果文件不存在则创建文件
log_path = read_file("./nginx.log")[0]
for line in read_line(log_path):
matches = parse_log(line)
if matches == None:
print "match fail, line: %s" % line
continue
date = matches.group("date")
month = matches.group("month")
year = matches.group("year")
day_time = matches.group("day_time")
ctime = parse_time(date, month, year, day_time)
print ctime
write_line(time_file, str(ctime))
输出结果
产生文件time.log,内容如下:
806909465
806909465
806909465
806909466
806909466
806909466
参考文献
本文作者: seawish
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
网友评论