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中的私有属性
Aug 21 Python
浅谈Python 的枚举 Enum
Jun 12 Python
Python中的pygal安装和绘制直方图代码分享
Dec 08 Python
Django 跨域请求处理的示例代码
May 02 Python
解决Python设置函数调用超时,进程卡住的问题
Aug 08 Python
django 多对多表的创建和插入代码实现
Sep 09 Python
PyTorch中permute的用法详解
Dec 30 Python
Pytorch保存模型用于测试和用于继续训练的区别详解
Jan 10 Python
Python标准库json模块和pickle模块使用详解
Mar 10 Python
关于Django Models CharField 参数说明
Mar 31 Python
django项目中新增app的2种实现方法
Apr 01 Python
python 实现朴素贝叶斯算法的示例
Sep 30 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获取mysql版本的几种方法小结
2008/03/25 PHP
mysql下创建字段并设置主键的php代码
2010/05/16 PHP
php中使用PHPExcel读写excel(xls)文件的方法
2014/09/15 PHP
利用Laravel生成Gravatar头像地址的优雅方法
2017/12/30 PHP
js关闭当前页面(窗口)的几种方式总结
2013/03/05 Javascript
jquery对dom的操作常用方法整理
2013/06/25 Javascript
div浮层,滚动条移动,位置保持不变的4种方法汇总
2013/12/11 Javascript
Javascript selection的兼容性写法介绍
2013/12/20 Javascript
js 获取经纬度的实现方法
2016/06/20 Javascript
javascript汉字拼音互转的简单实例
2016/10/09 Javascript
浅谈jquery中使用canvas的问题
2016/10/10 Javascript
javascript浏览器用户代理检测脚本实现方法
2017/10/27 Javascript
Vue 2.0学习笔记之使用$refs访问Vue中的DOM
2017/12/19 Javascript
nodeJs实现基于连接池连接mysql的方法示例
2018/02/10 NodeJs
AngularJS对动态增加的DOM实现ng-keyup事件示例
2018/03/12 Javascript
vue中使用element-ui进行表单验证的实例代码
2018/06/22 Javascript
p5.js临摹旋转爱心
2019/10/23 Javascript
vue中使用rem布局代码详解
2019/10/30 Javascript
JS变量提升及函数提升实例解析
2020/09/03 Javascript
JavaScript获取时区实现过程解析
2020/09/24 Javascript
Ant design vue中的联动选择取消操作
2020/10/31 Javascript
[13:56]DAC2018 4.5SOLO赛决赛 MidOne vs Paparazi第一场
2018/04/06 DOTA
Python的时间模块datetime详解
2017/04/17 Python
python实现文本界面网络聊天室
2018/12/12 Python
Python从列表推导到zip()函数的5种技巧总结
2019/10/23 Python
Reebok俄罗斯官方网上商店:购买锐步运动服装和鞋子
2016/09/26 全球购物
美国婚戒购物网站:Anjays Designs
2017/06/28 全球购物
试用期转正后的自我评价
2014/09/21 职场文书
村主任个人对照检查材料
2014/10/01 职场文书
2014年销售助理工作总结
2014/12/01 职场文书
党风廉政建设调研报告
2015/01/01 职场文书
乡镇法制宣传日活动总结
2015/05/05 职场文书
执行力心得体会范文
2016/01/11 职场文书
goland设置颜色和字体的操作
2021/05/05 Golang
使用pandas或numpy处理数据中的空值(np.isnan()/pd.isnull())
2021/05/14 Python
如何在python中实现ECDSA你知道吗
2021/11/23 Python