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 相关文章推荐
haskell实现多线程服务器实例代码
Nov 26 Python
让python同时兼容python2和python3的8个技巧分享
Jul 11 Python
Python中用于计算对数的log()方法
May 15 Python
在Django的模板中使用认证数据的方法
Jul 23 Python
python3使用urllib模块制作网络爬虫
Apr 08 Python
python调用系统ffmpeg实现视频截图、http发送
Mar 06 Python
python3 常见解密加密算法实例分析【base64、MD5等】
Dec 19 Python
pytorch之添加BN的实现
Jan 06 Python
将pytorch转成longtensor的简单方法
Feb 18 Python
QML用PathView实现轮播图
Jun 03 Python
Python dict的常用方法示例代码
Jun 23 Python
python自动打开浏览器下载zip并提取内容写入excel
Jan 04 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
ThinkPHP中实例Model方法的区别说明
2010/08/21 PHP
利用php实现禁用IE和火狐的缓存问题
2012/12/03 PHP
Smarty模板学习笔记之Smarty简介
2014/05/20 PHP
php通过正则表达式记取数据来读取xml的方法
2015/03/09 PHP
浅谈PHP中JSON数据操作
2015/07/01 PHP
thinkPHP批量删除的实现方法分析
2016/11/09 PHP
PHP 多任务秒级定时器的实现方法
2018/05/13 PHP
2007/12/23更新创意无限,简单实用(javascript log)
2007/12/24 Javascript
读jQuery之三(构建选择器)
2011/06/11 Javascript
jWiard 基于JQuery的强大的向导控件介绍
2011/10/28 Javascript
2014最热门的JavaScript代码高亮插件推荐
2014/11/25 Javascript
跟我学习javascript的异步脚本加载
2015/11/20 Javascript
JS如何判断json是否为空
2016/07/06 Javascript
AngularJs 国际化(I18n/L10n)详解
2016/09/01 Javascript
Node.js测试中的Mock文件系统详解
2016/11/21 Javascript
jQuery插件Echarts实现的渐变色柱状图
2017/03/23 jQuery
Bootstrap输入框组件使用详解
2017/06/09 Javascript
分享vue里swiper的一些坑
2018/08/30 Javascript
微信小程序开发之tabbar图标和颜色的实现
2018/10/17 Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【凹多边形的分离轴检测算法】
2018/12/13 Javascript
layer扩展打开/关闭动画的方法
2019/09/23 Javascript
小程序实现录音上传功能
2019/11/22 Javascript
[06:25]第二届DOTA2亚洲邀请赛主赛事第二天比赛集锦.mp4
2017/04/03 DOTA
python 切片和range()用法说明
2013/03/24 Python
浅谈Python的异常处理
2016/06/19 Python
python如何查看系统网络流量的信息
2016/09/12 Python
利用Python如何将数据写到CSV文件中
2018/06/05 Python
Python openpyxl 遍历所有sheet 查找特定字符串的方法
2018/12/10 Python
我用Python抓取了7000 多本电子书案例详解
2019/03/25 Python
Python3使用TCP编写一个简易的文件下载器功能
2019/05/08 Python
html5摇一摇代码优化包括DeviceMotionEvent等等
2014/09/01 HTML / CSS
P/Invoke是什么
2015/07/31 面试题
2014乡党委副书记党建工作汇报材料
2014/11/02 职场文书
社区党支部公开承诺书
2015/04/29 职场文书
中职班主任培训心得体会
2016/01/07 职场文书
python多线程方法详解
2022/01/18 Python