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之入门(四)运算
May 27 Python
python循环监控远程端口的方法
Mar 14 Python
python使用pil生成缩略图的方法
Mar 26 Python
python中as用法实例分析
Apr 30 Python
Python对列表排序的方法实例分析
May 16 Python
分析python切片原理和方法
Dec 19 Python
python编辑用户登入界面的实现代码
Jul 16 Python
tensorflow实现tensor中满足某一条件的数值取出组成新的tensor
Jan 04 Python
python正则表达式实例代码
Mar 03 Python
python字典与json转换的方法总结
Dec 28 Python
彻底弄懂Python中的回调函数(callback)
Jun 25 Python
Python 读取千万级数据自动写入 MySQL 数据库
Jun 28 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
介绍几个array库的新函数 php
2006/12/29 PHP
利用中国天气预报接口实现简单天气预报
2014/01/20 PHP
PHP简单选择排序算法实例
2015/01/26 PHP
php检索或者复制远程文件的方法
2015/03/13 PHP
thinkPHP简单导入和使用阿里云OSSsdk的方法
2017/03/15 PHP
JavaScript获取GridView中用户点击控件的行号,列号
2009/04/14 Javascript
jquery批量设置属性readonly和disabled的方法
2014/01/24 Javascript
快速学习JavaScript的6个思维技巧
2015/10/13 Javascript
详解AngularJs中$resource和restfu服务端数据交互
2016/09/21 Javascript
在vue中通过axios异步使用echarts的方法
2018/01/13 Javascript
JS中Promise函数then的奥秘探究
2018/07/30 Javascript
vue后台管理之动态加载路由的方法
2018/08/13 Javascript
JQuery 实现文件下载的常用方法分析
2019/10/29 jQuery
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
vue.js 实现a标签href里添加参数
2019/11/12 Javascript
微信小程序点击按钮动态切换input的disabled禁用/启用状态功能
2020/03/07 Javascript
解决vue项目中遇到 Cannot find module ‘chalk‘ 报错的问题
2020/11/05 Javascript
python中pycurl库的用法实例
2014/09/30 Python
Python实现从订阅源下载图片的方法
2015/03/11 Python
Python爬虫工程师面试问题总结
2018/03/22 Python
对python opencv 添加文字 cv2.putText 的各参数介绍
2018/12/05 Python
Django2.1集成xadmin管理后台所遇到的错误集锦(填坑)
2018/12/20 Python
解决Python 使用h5py加载文件,看不到keys()的问题
2019/02/08 Python
Python如何爬取微信公众号文章和评论(基于 Fiddler 抓包分析)
2019/06/28 Python
Pytorch evaluation每次运行结果不同的解决
2020/01/02 Python
Ruby如何定义一个类
2012/10/08 面试题
双语教学实施方案
2014/03/23 职场文书
关于建议书的格式范文
2014/05/20 职场文书
超市七夕促销活动方案
2014/08/28 职场文书
公安局负责人查摆问题及整改方案
2014/09/27 职场文书
司机岗位职责范本
2015/04/10 职场文书
销售口号霸气押韵
2015/12/24 职场文书
反腐倡廉心得体会2016
2016/01/13 职场文书
三严三实·严以律己心得体会
2016/01/13 职场文书
Python-OpenCV教程之图像的位运算详解
2021/06/21 Python
CSS精灵图的原理与使用方法介绍
2022/03/17 HTML / CSS