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搭建Django应用程序步骤及版本冲突问题解决
Nov 19 Python
Python正则表达式匹配HTML页面编码
Apr 08 Python
Python实现扫描局域网活动ip(扫描在线电脑)
Apr 28 Python
python的多重继承的理解
Aug 06 Python
用tensorflow搭建CNN的方法
Mar 05 Python
python argparser的具体使用
Nov 10 Python
如何分离django中的媒体、静态文件和网页
Nov 12 Python
Pycharm中import torch报错的快速解决方法
Mar 05 Python
Python新手如何理解循环加载模块
May 29 Python
Python自动化操作实现图例绘制
Jul 09 Python
Python 实现将某一列设置为str类型
Jul 14 Python
Python常用数字处理基本操作汇总
Sep 10 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在线打包程序源码
2008/07/27 PHP
深入解析php中的foreach问题
2013/06/30 PHP
在CentOS上搭建LAMP+vsftpd环境的简单指南
2015/08/01 PHP
[原创]图片分页查看
2006/08/28 Javascript
JS数组操作(数组增加、删除、翻转、转字符串、取索引、截取(切片)slice、剪接splice、数组合并)
2016/05/20 Javascript
js简单判断flash是否加载完成的方法
2016/06/21 Javascript
javascript中的 object 和 function小结
2016/08/14 Javascript
微信小程序 教程之注册页面
2016/10/17 Javascript
jQuery密码强度验证控件使用详解
2017/01/05 Javascript
javascript填充默认头像方法
2018/02/22 Javascript
微信小程序地图(map)组件点击(tap)获取经纬度的方法
2019/01/10 Javascript
Node.js + express基本用法教程
2019/03/14 Javascript
用原生 JS 实现 innerHTML 功能实例详解
2019/04/03 Javascript
jQuery - AJAX load() 实例用法详解
2019/08/27 jQuery
详解Vue Cli浏览器兼容性实践
2020/06/08 Javascript
JavaScript this指向相关原理及实例解析
2020/07/10 Javascript
antd table按表格里的日期去排序操作
2020/11/17 Javascript
Python的print用法示例
2014/02/11 Python
python查看FTP是否能连接成功的方法
2015/07/30 Python
Python 逐行分割大txt文件的方法
2017/10/10 Python
python爬取m3u8连接的视频
2018/02/28 Python
关于python2 csv写入空白行的问题
2018/06/22 Python
python学习之hook钩子的原理和使用
2018/10/25 Python
关于不懂Chromedriver如何配置环境变量问题解决方法
2019/06/12 Python
Django框架之DRF 基于mixins来封装的视图详解
2019/07/23 Python
在Python中等距取出一个数组其中n个数的实现方式
2019/11/27 Python
对pytorch的函数中的group参数的作用介绍
2020/02/18 Python
python实现视频压缩功能
2020/12/18 Python
AE美国鹰日本官方网站: American Eagle Outfitters
2016/12/10 全球购物
Sofft鞋官网:世界知名鞋类品牌
2017/03/28 全球购物
关于旷工的检讨书
2014/02/02 职场文书
舞蹈兴趣小组活动总结
2014/07/07 职场文书
文明社区申报材料
2014/08/21 职场文书
法人代表证明书
2014/09/18 职场文书
文体活动总结
2015/02/04 职场文书
mysql数据库入门第一步之创建表
2021/05/14 MySQL