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调用windows api锁定计算机示例
Apr 17 Python
Python实现求两个csv文件交集的方法
Sep 06 Python
Python爬虫实战之12306抢票开源
Jan 24 Python
anaconda如何查看并管理python环境
Jul 05 Python
Python内存管理实例分析
Jul 10 Python
opencv转换颜色空间更改图片背景
Aug 20 Python
python如何求数组连续最大和的示例代码
Feb 04 Python
python进行参数传递的方法
May 12 Python
使用Pycharm在运行过程中,查看每个变量的操作(show variables)
Jun 08 Python
解决python的空格和tab混淆而报错的问题
Feb 26 Python
聊一聊python常用的编程模块
May 14 Python
python如何正确使用yield
May 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导出Redis数据到另一个Redis中的代码
2014/03/12 PHP
为百度UE编辑器上传图片添加水印功能
2015/04/16 PHP
php防止网站被攻击的应急代码
2015/10/21 PHP
PHP实现链式操作的原理详解
2016/09/16 PHP
PHP流Streams、包装器wrapper概念与用法实例详解
2017/11/17 PHP
PHP文件上传小程序 适合初学者学习!
2019/05/23 PHP
Firefox window.close()的使用注意事项
2009/04/11 Javascript
在新窗口打开超链接的方法小结
2013/04/14 Javascript
jQuery学习笔记之jQuery.extend(),jQuery.fn.extend()分析
2014/06/09 Javascript
javascript实现网页屏蔽Backspace事件,输入框不屏蔽
2015/07/21 Javascript
jquery+html5时钟特效代码分享(可设置闹钟并且语音提醒)
2020/03/30 Javascript
详解js中Json的语法与格式
2016/11/22 Javascript
微信小程序 登录的简单实现
2017/04/19 Javascript
详解使用vue实现tab 切换操作
2017/07/03 Javascript
vue单个组件实现无限层级多选菜单功能
2018/04/10 Javascript
ES6之模版字符串的具体使用
2018/05/17 Javascript
vuejs2.0运用原生js实现简单拖拽元素功能
2020/08/21 Javascript
在Vue项目中取消ESLint代码检测的步骤讲解
2019/01/27 Javascript
JSX在render函数中的应用详解
2019/09/04 Javascript
JS对日期操作封装代码实例
2019/11/08 Javascript
Layui实现主窗口和Iframe层参数传递
2019/11/14 Javascript
python实现在pandas.DataFrame添加一行
2018/04/04 Python
Python实现的连接mssql数据库操作示例
2018/08/17 Python
用Python实现读写锁的示例代码
2018/11/05 Python
Python数据类型之列表和元组的方法实例详解
2019/07/08 Python
美国领先的汽车轮胎和轮毂供应商:TireBuyer
2016/07/21 全球购物
《再别康桥》教学反思
2014/02/12 职场文书
写自荐信的注意事项
2014/03/09 职场文书
公司年底活动方案
2014/08/17 职场文书
作风整顿剖析材料
2014/09/30 职场文书
2014年销售工作总结范文
2014/12/01 职场文书
考研复习计划
2015/01/19 职场文书
小班上学期个人总结
2015/02/12 职场文书
2016党员干部反腐倡廉心得体会
2016/01/13 职场文书
导游词之杭州岳王庙
2019/11/13 职场文书
vue/cli 配置动态代理无需重启服务的方法
2022/05/20 Vue.js