python实时分析日志的一个小脚本分享


Posted in Python onMay 07, 2017

前言

大家都知道Web运维总要关注相关域名的实时2xx/s、4xx/s、5xx/s、响应时间、带宽等这些指标,之前的日志是五分钟一分割,简单的用awk就可以了,现在由于要推送日志到ELK,继续之前五分钟一分割会有问题,就改为一天分割一次。改成一天一分割后,显然再继续用Shell就不合适了,于是就用Python写了下。

方法如下:

脚本主要运用了文件的seek和tell函数,原理如下:

       1.加入crontab,每5分钟执行一次

       2.只分析从上次读取日志文件的结束位置到这次读取文件时的末尾位置之间的日志,出结果
可以使用zabbix_sender把结果发送到zabbix server或者直接使用zabbix agent来读取这个文件取数据,配合zabbix出图、做报警,代码如下:

#!/usr/bin/env python
#coding: utf-8

from __future__ import division
import os

LOG_FILE = '/data0/logs/nginx/xxxx-access_log'
POSITION_FILE = '/tmp/position.log'
STATUS_FILE = '/tmp/http_status'
#crontab 执行时间
CRON_TIME = 300

def get_position():
 #第一次读取日志文件,POSITION_FILE为空
 if not os.path.exists(POSITION_FILE):
  start_position = str(0)
  end_position = str(os.path.getsize(LOG_FILE))
  fh = open(POSITION_FILE,'w')
  fh.write('start_position: %s\n' % start_position)
  fh.write('end_position: %s\n' % end_position)
  fh.close()
  os._exit(1)
 else:
  fh = open(POSITION_FILE)
  se = fh.readlines()
  fh.close()
  #其他意外情况导致POSITION_FILE内容不是两行
  if len(se) != 2:
   os.remove(POSITION_FILE)
   os._exit(1)
  last_start_position,last_end_position = [item.split(':')[1].strip() for item in se]
  start_position = last_end_position
  end_position = str(os.path.getsize(LOG_FILE))
  #日志轮转导致start_position > end_position
  #print start_position,end_position
  if start_position > end_position:
   start_position = 0
  #日志停止滚动时
  elif start_position == end_position:
   os._exit(1)
  #print start_position,end_position
  fh = open(POSITION_FILE,'w')
  fh.write('start_position: %s\n' % start_position)
  fh.write('end_position: %s\n' % end_position)
  fh.close()
  return map(int,[start_position,end_position])

def write_status(content):
 fh = open(STATUS_FILE,'w')
 fh.write(content)
 fh.close()

def handle_log(start_position,end_position):
 log = open(LOG_FILE)
 log.seek(start_position,0)
 status_2xx,status_403,status_404,status_500,status_502,status_503,status_504,status_all,rt,bandwidth = 0,0,0,0,0,0,0,0,0,0
 while True:
  current_position = log.tell()
  if current_position >= end_position:
   break
  line = log.readline()
  line = line.split(' ')
  host,request_time,time_local,status,bytes_sent = line[1],line[3],line[5],line[10],line[11]
  #print host,request_time,time_local,status,bytes_sent
  status_all += 1
  try:
   rt += float(request_time.strip('s'))
   bandwidth += int(bytes_sent)
  except:
   pass
  if status == '200' or status == '206':
   status_2xx += 1
  elif status == '403':
   status_403 += 1
  elif status == '404':
   status_404 += 1
  elif status == '500':
   status_500 += 1
  elif status == '502':
   status_502 += 1
  elif status == '503':
   status_503 += 1
  elif status == '504':
   status_504 += 1
 log.close()
 #print "status_2xx: %s\nstatus_403: %s\nstatus_404: %s\nstatus_500: %s\nstatus_502: %s\nstatus_503: %s\nstatus_504: %s\nstatus_all: %s\nrt: %s\nbandwidth: %s\n" % (status_2xx/CRON_TIME,status_403/CRON_TIME,status_404/CRON_TIME,status_500/CRON_TIME,status_502/CRON_TIME,status_503/CRON_TIME,status_504/CRON_TIME,status_all/CRON_TIME,rt/status_all,bandwidth/CRON_TIME)

 write_status("status_2xx: %s\nstatus_403: %s\nstatus_404: %s\nstatus_500: %s\nstatus_502: %s\nstatus_503: %s\nstatus_504: %s\nstatus_all: %s\nrt: %s\nbandwidth: %s\n" % (status_2xx/CRON_TIME,status_403/CRON_TIME,status_404/CRON_TIME,status_500/CRON_TIME,status_502/CRON_TIME,status_503/CRON_TIME,status_504/CRON_TIME,status_all/CRON_TIME,rt/status_all,bandwidth/CRON_TIME))

if __name__ == '__main__':
 start_position,end_position = get_position()
 handle_log(start_position,end_position)

看下分析的结果:

cat /tmp/http_status
status_2xx: 17.3333333333
status_403: 0.0
status_404: 1.0
status_500: 0.0
status_502: 0.0
status_503: 0.0
status_504: 0.0
status_all: 20.0
rt: 0.0782833333333
bandwidth: 204032.0

后来发现有点问题,start_position、end_position 使用字符串比较会有问题,如下:

In [5]: '99772400' > '100227572'
Out[5]: True

In [6]: int('99772400') > int('100227572')
Out[6]: False

因此,更正为:

#日志轮转导致start_position > end_position
#print start_position,end_position
if int(start_position) > int(end_position):
 start_position = 0
#日志停止滚动时
elif int(start_position) == int(end_position):
 os._exit(1)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python 实现堆排序算法代码
Jun 05 Python
python判断字符串是否包含子字符串的方法
Mar 24 Python
轻松掌握python设计模式之访问者模式
Nov 18 Python
详谈Python3 操作系统与路径 模块(os / os.path / pathlib)
Apr 26 Python
python删除文本中行数标签的方法
May 31 Python
解决tensorflow测试模型时NotFoundError错误的问题
Jul 27 Python
Python 使用元类type创建类对象常见应用详解
Oct 17 Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
May 13 Python
python openssl模块安装及用法
Dec 06 Python
pycharm实现猜数游戏
Dec 07 Python
python 实现Harris角点检测算法
Dec 11 Python
Python基于百度AI实现抓取表情包
Jun 27 Python
python分割列表(list)的方法示例
May 07 #Python
Python 常用的安装Module方式汇总
May 06 #Python
python中OrderedDict的使用方法详解
May 05 #Python
Python编程生成随机用户名及密码的方法示例
May 05 #Python
Python实现统计文本文件字数的方法
May 05 #Python
Python部署web开发程序的几种方法
May 05 #Python
Python中异常重试的解决方案详解
May 05 #Python
You might like
javascript CSS画图之基础篇
2009/07/29 Javascript
JQuery开发的数独游戏代码
2010/10/29 Javascript
JS实现Enter键跳转及控件获得焦点
2013/08/12 Javascript
使用JavaScript修改浏览器URL地址栏的实现代码
2013/10/21 Javascript
jQuery toggle 代替方法
2016/03/22 Javascript
JavaScript实现图片自动加载的瀑布流效果
2016/04/11 Javascript
JS定义类的六种方式详解
2016/05/12 Javascript
详细谈谈AngularJS的子级作用域问题
2016/09/05 Javascript
jQuery中页面返回顶部的方法总结
2016/12/30 Javascript
jQuery实现对象转为url参数的方法
2017/01/11 Javascript
JS简单添加元素新节点的方法示例
2018/02/10 Javascript
Vue 2.5.2下axios + express 本地请求404的解决方法
2018/02/21 Javascript
详解JavaScript中关于this指向的4种情况
2019/04/18 Javascript
vue使用i18n实现国际化的方法详解
2019/09/05 Javascript
vue-amap根据地址回显地图并mark的操作
2020/11/03 Javascript
[04:59]2018DOTA2亚洲邀请赛 4.7 Mineski夺冠时刻
2018/04/09 DOTA
Python遍历zip文件输出名称时出现乱码问题的解决方法
2015/04/08 Python
轻松理解Python 中的 descriptor
2017/09/15 Python
利用Tkinter(python3.6)实现一个简单计算器
2017/12/21 Python
Pandas 按索引合并数据集的方法
2018/11/15 Python
对python自动生成接口测试的示例讲解
2018/11/30 Python
Python自动生成代码 使用tkinter图形化操作并生成代码框架
2019/09/18 Python
python 一维二维插值实例
2020/04/22 Python
Python标准库:内置函数max(iterable, *[, key, default])说明
2020/04/25 Python
Html5 new XMLHttpRequest()监听附件上传进度
2021/01/14 HTML / CSS
美国最大的农村生活方式零售店:Tractor Supply Company(TSC)
2017/05/15 全球购物
美国在线眼镜商城:Eyeglasses.com
2017/06/26 全球购物
Dr. Martens马汀博士澳大利亚官网:马丁靴鼻祖
2019/07/02 全球购物
党支部书记岗位责任制
2014/02/11 职场文书
入党积极分子学习两会心得体会范文
2014/03/17 职场文书
学校清明节活动总结
2014/07/04 职场文书
全国法制宣传日活动总结2014
2014/11/01 职场文书
小学新教师个人总结
2015/02/05 职场文书
企业财务经理岗位职责
2015/04/08 职场文书
幼儿园教师暑期培训心得体会
2016/01/09 职场文书
提升Nginx性能的一些建议
2021/03/31 Servers