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实现简单QQ单用户机器人的方法
Jul 03 Python
Python中你应该知道的一些内置函数
Mar 31 Python
python 中split 和 strip的实例详解
Jul 12 Python
Python 实现使用dict 创建二维数据、DataFrame
Apr 13 Python
python 3.7.0 安装配置方法图文教程
Aug 27 Python
利用Python查看微信共同好友功能的实现代码
Apr 24 Python
Python Scrapy图片爬取原理及代码实例
Jun 12 Python
浅谈keras 的抽象后端(from keras import backend as K)
Jun 16 Python
python如何求圆的面积
Jul 01 Python
Pycharm打开已有项目配置python环境的方法
Jul 03 Python
详解向scrapy中的spider传递参数的几种方法(2种)
Sep 28 Python
Python使用mitmproxy工具监控手机 下载手机小视频
Apr 18 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
php自定义函数截取汉字长度
2014/05/15 PHP
php判断手机浏览还是web浏览,并执行相应的动作简单实例
2016/07/28 PHP
php加密之discuz内容经典加密方式实例详解
2017/02/04 PHP
PHP实现的大文件切割与合并功能示例
2018/04/10 PHP
PHP写API输出的时用echo的原因详解
2019/04/28 PHP
从零开始学习jQuery (八) 插播:jQuery实施方案
2011/02/23 Javascript
非主流的textarea自增长实现js代码
2011/12/20 Javascript
DIV+CSS+JS不间断横向滚动实现代码
2013/03/19 Javascript
JavaScript中访问节点对象的方法有哪些如何使用
2013/09/24 Javascript
浅谈Javascript如何实现匀速运动
2014/12/19 Javascript
微信小程序 Page()函数详解
2016/10/17 Javascript
前端面试知识点锦集(JavaScript篇)
2016/12/28 Javascript
node学习记录之搭建web服务器教程
2017/02/16 Javascript
JS实现验证码倒计时的注册页面
2018/01/02 Javascript
Jquery实现获取子元素的方法分析
2019/08/24 jQuery
JS实现基本的网页计算器功能示例
2020/01/16 Javascript
js实现无缝轮播图特效
2020/05/09 Javascript
nuxt 服务器渲染动态设置 title和seo关键字的操作
2020/11/05 Javascript
[54:56]DOTA2上海特级锦标赛主赛事日 - 5 总决赛Liquid VS Secret第三局
2016/03/06 DOTA
使用python编写android截屏脚本双击运行即可
2014/07/21 Python
Python列表(List)知识点总结
2019/02/18 Python
python实现矩阵打印
2019/03/02 Python
Python使用sqlalchemy模块连接数据库操作示例
2019/03/13 Python
python 计算一个字符串中所有数字的和实例
2019/06/11 Python
python虚拟环境完美部署教程
2019/08/06 Python
tensorflow模型保存、加载之变量重命名实例
2020/01/21 Python
python如何将图片转换素描画
2020/09/08 Python
老板电器官方购物商城:老板油烟机、燃气灶、消毒柜、电烤箱
2018/05/30 全球购物
含精油的天然有机化妆品:Indemne
2019/08/27 全球购物
商场中秋节活动方案
2014/02/07 职场文书
见习期自我鉴定范文
2014/03/19 职场文书
专家推荐信模板
2014/05/09 职场文书
诚实守信道德模范事迹材料
2014/08/15 职场文书
城管执法人员纪律作风整顿思想汇报
2014/09/13 职场文书
销售人才自我评价范文
2014/09/27 职场文书
优秀团队申报材料
2014/12/26 职场文书