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实现socket端口重定向示例
Feb 10 Python
Python中实现结构相似的函数调用方法
Mar 10 Python
python实现多线程抓取知乎用户
Dec 12 Python
对python中的 os.mkdir和os.mkdirs详解
Oct 16 Python
python添加菜单图文讲解
Jun 04 Python
jupyter notebook 使用过程中python莫名崩溃的原因及解决方式
Apr 10 Python
解决Python paramiko 模块远程执行ssh 命令 nohup 不生效的问题
Jul 14 Python
Python selenium如何打包静态网页并下载
Aug 12 Python
python/golang实现循环链表的示例代码
Sep 14 Python
如何将anaconda安装配置的mmdetection环境离线拷贝到另一台电脑
Oct 15 Python
python实现模拟器爬取抖音评论数据的示例代码
Jan 06 Python
字典算法实现及操作 --python(实用)
Mar 31 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
真正面向对象编程:PHP5.01发布
2006/10/09 PHP
解析用PHP实现var_export的详细介绍
2013/06/20 PHP
PHP内置过滤器FILTER使用实例
2014/06/25 PHP
php实现处理输入转义字符的代码
2015/11/08 PHP
PHP的消息通信机制测试实例
2016/11/10 PHP
PHP从零开始打造自己的MVC框架之入口文件实现方法详解
2019/06/03 PHP
Textbox控件注册回车事件及触发按钮提交事件具体实现
2013/03/04 Javascript
jQuery中的height innerHeight outerHeight区别示例介绍
2014/06/15 Javascript
javascript学习笔记(四)function函数部分
2014/09/30 Javascript
JS实现控制表格行文本对齐的方法
2015/03/30 Javascript
js实现简单排列组合的方法
2016/01/27 Javascript
jQuery中借助deferred来请求及判断AJAX加载的实例讲解
2016/05/24 Javascript
js删除Array数组中指定元素的两种方法
2016/08/03 Javascript
BootStrap中Table分页插件使用详解
2016/10/09 Javascript
jQuery 插件实现随机自由弹跳气泡样式
2017/01/12 Javascript
原生js实现鼠标跟随效果
2017/02/28 Javascript
vue中如何实现变量和字符串拼接
2017/06/19 Javascript
解决Extjs下拉框不显示的问题
2017/06/21 Javascript
React Native 通告消息竖向轮播组件的封装
2020/08/25 Javascript
一步步教你利用webpack如何搭一个vue脚手架(超详细讲解和注释)
2018/01/08 Javascript
Vue-router 切换组件页面时进入进出动画方法
2018/09/01 Javascript
JS监听滚动和id自动定位滚动
2018/12/18 Javascript
JS使用JSON.parse(),JSON.stringify()实现对对象的深拷贝功能分析
2019/03/06 Javascript
Vue路由守卫及页面登录权限控制的设置方法(两种)
2020/03/31 Javascript
python Matplotlib画图之调整字体大小的示例
2017/11/20 Python
Python 访问限制 private public的详细介绍
2018/10/16 Python
python实现生成字符串大小写字母和数字的各种组合
2019/01/01 Python
python实现接口并发测试脚本
2019/06/25 Python
python中numpy.empty()函数实例讲解
2021/02/05 Python
印度低票价航空公司:GoAir
2017/10/11 全球购物
时尚设计师手表:The Watch Cabin
2018/10/06 全球购物
成人毕业生自我鉴定
2013/10/18 职场文书
高一英语教学反思
2014/01/22 职场文书
cf收人广告词
2014/03/14 职场文书
先进教育工作者事迹材料
2014/12/23 职场文书
给女朋友道歉的话大全
2015/01/20 职场文书