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中random模块生成随机数详解
Mar 10 Python
python 表达式和语句及for、while循环练习实例
Jul 07 Python
Python代码实现KNN算法
Dec 20 Python
Python分析彩票记录并预测中奖号码过程详解
Jul 09 Python
python 抓包保存为pcap文件并解析的实例
Jul 23 Python
Pycharm创建项目时如何自动添加头部信息
Nov 14 Python
python飞机大战 pygame游戏创建快速入门详解
Dec 17 Python
详解Python3 中的字符串格式化语法
Jan 15 Python
python实现简单的购物程序代码实例
Mar 03 Python
Python实现加密的RAR文件解压的方法(密码已知)
Sep 11 Python
Visual Studio code 配置Python开发环境
Sep 11 Python
Python基本数据类型之字符串str
Jul 21 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 模拟POST|GET操作实现代码
2010/07/20 PHP
PHP验证码类代码( 最新修改,完全定制化! )
2010/12/02 PHP
php数组函数序列之array_search()- 按元素值返回键名
2011/11/04 PHP
PHP得到mssql的存储过程的输出参数功能实现
2012/11/23 PHP
PHP命名空间(Namespace)的使用详解
2013/05/04 PHP
php float不四舍五入截取浮点型字符串方法总结
2013/10/28 PHP
Linux中用PHP判断程序运行状态的2个方法
2014/05/04 PHP
适用于初学者的简易PHP文件上传类
2015/10/29 PHP
100多行PHP代码实现socks5代理服务器[2]
2016/05/05 PHP
php中的抽象方法和抽象类
2017/02/14 PHP
Javascript入门学习资料收集整理篇
2008/07/06 Javascript
通过JQuery将DIV的滚动条滚动到指定的位置方便自动定位
2014/05/05 Javascript
jquery实现仿新浪微博带动画效果弹出层代码(可关闭、可拖动)
2015/10/12 Javascript
javascript运动效果实例总结(放大缩小、滑动淡入、滚动)
2016/01/08 Javascript
深入分析javascript中的错误处理机制
2016/07/17 Javascript
总结Node.js中的一些错误类型
2016/08/15 Javascript
jquery插件锦集【推荐】
2016/12/16 Javascript
微信小程序 解决请求服务器手机预览请求不到数据的方法
2017/01/04 Javascript
详解Vue基于 Nuxt.js 实现服务端渲染(SSR)
2018/04/05 Javascript
NodeJS服务器实现gzip压缩的示例代码
2018/10/12 NodeJs
vue中实现弹出层动画效果的示例代码
2020/09/25 Javascript
Vue + ts实现轮播插件的示例
2020/11/10 Javascript
基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能
2021/01/05 Vue.js
python模块restful使用方法实例
2013/12/10 Python
python装饰器-限制函数调用次数的方法(10s调用一次)
2018/04/21 Python
Python 的字典(Dict)是如何存储的
2019/07/05 Python
centos7中安装python3.6.4的教程
2019/12/11 Python
西班牙电子产品购物网站:Electronicamente
2018/07/26 全球购物
世界闻名的衬衫制造商:Savile Row Company
2018/07/30 全球购物
美国优质宠物用品购买网站:Muttropolis
2020/02/17 全球购物
当x.equals(y)等于true时,x.hashCode()与y.hashCode()可以不相等,这句话对不对
2015/05/02 面试题
设计总监岗位职责
2013/12/07 职场文书
建筑设计学生的自我评价
2014/01/16 职场文书
总经理岗位职责说明书
2014/07/30 职场文书
教师自我剖析材料(群众路线)
2014/09/29 职场文书
2015年业务工作总结范文
2015/04/10 职场文书