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中实现定制类的特殊方法总结
Sep 28 Python
python之Character string(实例讲解)
Sep 25 Python
Flask之flask-session的具体使用
Jul 26 Python
python3实现爬取淘宝美食代码分享
Sep 23 Python
Matplotlib中文乱码的3种解决方案
Nov 15 Python
对pandas通过索引提取dataframe的行方法详解
Feb 01 Python
django rest framework vue 实现用户登录详解
Jul 29 Python
解决python3 requests headers参数不能有中文的问题
Aug 21 Python
Python flask框架实现查询数据库并显示数据
Jun 04 Python
Python fileinput模块如何逐行读取多个文件
Oct 05 Python
Python实现小黑屋游戏的完整实例
Jan 06 Python
使用pd.merge表连接出现多余行的问题解决
Jun 16 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
关于文本留言本的分页代码
2006/10/09 PHP
php 需要掌握的东西 不做浮躁的人
2009/12/28 PHP
PHP伪静态Rewrite设置之APACHE篇
2014/07/30 PHP
如何批量清理系统临时文件(语言:C#、 C/C++、 php 、python 、java )
2016/02/01 PHP
PHP图形计数器程序显示网站用户浏览量
2016/07/20 PHP
php微信开发之自定义菜单完整流程
2016/10/08 PHP
PHP数据库操作二:memcache用法分析
2017/08/16 PHP
Javascript miscellanea -display data real time, using window.status
2007/01/09 Javascript
dwr spring的集成实现代码
2009/03/22 Javascript
jQuery之折叠面板的深入解析
2013/06/19 Javascript
nodejs 实现模拟form表单上传文件
2014/07/14 NodeJs
限制上传文件大小和格式的jQuery插件实例
2015/01/24 Javascript
使用JavaScript 实现的人脸检测
2015/03/24 Javascript
让图片跳跃起来  javascript图片轮播特效
2016/02/16 Javascript
JS仿京东移动端手指拨动切换轮播图效果
2020/04/10 Javascript
vue-cli+webpack记事本项目创建
2017/04/01 Javascript
JavaScript的setter与getter方法
2017/11/29 Javascript
vue 实现在函数中触发路由跳转的示例
2018/09/01 Javascript
如何封装了一个vue移动端下拉加载下一页数据的组件
2019/01/06 Javascript
java实现单链表增删改查的实例代码详解
2019/08/30 Javascript
python使用自定义user-agent抓取网页的方法
2015/04/15 Python
总结python爬虫抓站的实用技巧
2016/08/09 Python
python GUI库图形界面开发之PyQt5单选按钮控件QRadioButton详细使用方法与实例
2020/02/28 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
2020/03/20 Python
css3 给背景设置渐变色的方法
2019/09/12 HTML / CSS
html5 touch事件实现触屏页面上下滑动(一)
2016/03/10 HTML / CSS
Joules官网:女士、男士和儿童服装和鞋类
2018/10/23 全球购物
小学信息技术教学反思
2014/02/10 职场文书
贸易经济专业自荐书
2014/06/29 职场文书
检查机关党的群众路线个人整改措施
2014/10/04 职场文书
敲诈同学钱财检讨书范文
2014/11/18 职场文书
2014年乡镇卫生院工作总结
2014/11/24 职场文书
办公用房租赁协议书
2014/11/29 职场文书
优秀教师申报材料
2014/12/16 职场文书
北京天坛导游词
2015/02/12 职场文书
python 解决微分方程的操作(数值解法)
2021/05/26 Python