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使用PyV8执行javascript代码示例分享
Dec 04 Python
Python获取DLL和EXE文件版本号的方法
Mar 10 Python
详解Python中的序列化与反序列化的使用
Jun 30 Python
深入理解python对json的操作总结
Jan 05 Python
5个很好的Python面试题问题答案及分析
Jan 19 Python
使用Python制作微信跳一跳辅助
Jan 31 Python
python logging模块的使用总结
Jul 09 Python
python正则爬取某段子网站前20页段子(request库)过程解析
Aug 10 Python
Python小白垃圾回收机制入门
Jun 09 Python
深入理解Python 多线程
Jun 16 Python
keras 回调函数Callbacks 断点ModelCheckpoint教程
Jun 18 Python
keras用auc做metrics以及早停实例
Jul 02 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调用Oracle存储过程
2006/10/09 PHP
win7下memCache的安装过程(具体操作步骤)
2013/06/28 PHP
JavaScript 学习笔记(七)字符串的连接
2009/12/31 Javascript
JavaScript中valueOf函数与toString方法深入理解
2012/12/02 Javascript
jquery解析XML字符串和XML文件的方法说明
2014/02/21 Javascript
jquery删除指定的html标签并保留标签内文本内容的方法
2014/04/02 Javascript
动态加载iframe时get请求传递中文参数乱码解决方法
2014/05/07 Javascript
IE10中flexigrid无法显示数据的解决方法
2015/07/26 Javascript
jQuery实现textarea自动增长宽高的方法
2015/12/18 Javascript
快速使用Bootstrap搭建传送带
2016/05/06 Javascript
jQuery选择器基础入门教程
2016/05/10 Javascript
Bootstrap CSS布局之图像
2016/12/17 Javascript
JavaScript中Promise的使用详解
2017/02/26 Javascript
在vue-cli中组件通信的方法
2017/12/16 Javascript
jQuery实现鼠标响应式透明度渐变动画效果示例
2018/02/13 jQuery
Angular学习教程之RouterLink花式跳转
2018/05/03 Javascript
Makefile/cmake/node-gyp中区分判断不同平台的方法
2018/12/18 Javascript
JavaScript使用Math.random()生成简单的验证码
2019/01/21 Javascript
微信小程序实现带放大效果的轮播图
2020/05/26 Javascript
jQuery实现穿梭框效果
2021/01/19 jQuery
[01:53]DOTA2超级联赛专访Zhou 五年职业青春成长
2013/05/29 DOTA
[02:51]DOTA2 Supermajor小组分组对阵抽签仪式
2018/06/01 DOTA
Python类的多重继承问题深入分析
2014/11/09 Python
Python多线程和队列操作实例
2015/06/21 Python
python万年历实现代码 含运行结果
2017/05/20 Python
对python中for、if、while的区别与比较方法
2018/06/25 Python
python和mysql交互操作实例详解【基于pymysql库】
2019/06/04 Python
设置jupyter中DataFrame的显示限制方式
2020/04/12 Python
美国最大的高尔夫发球时间预订网站:TeeOff.com
2018/03/28 全球购物
优秀导游先进事迹材料
2014/01/25 职场文书
幼儿园运动会加油词
2014/02/14 职场文书
检举信的格式及范文
2014/04/04 职场文书
办公室打字员岗位职责
2014/04/16 职场文书
人力资源管理毕业求职信
2014/08/05 职场文书
乡镇干部学习心得体会
2016/01/23 职场文书
vue中data里面的数据相互使用方式
2022/06/05 Vue.js