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基于sftp及rsa密匙实现远程拷贝文件的方法
Sep 21 Python
利用python模拟sql语句对员工表格进行增删改查
Jul 05 Python
Python3爬虫全国地址信息
Jan 05 Python
python对列进行平移变换的方法(shift)
Jan 10 Python
django认证系统 Authentication使用详解
Jul 22 Python
python并发编程多进程 模拟抢票实现过程
Aug 20 Python
使用Python的Turtle绘制哆啦A梦实例
Nov 21 Python
python爬虫模拟浏览器的两种方法实例分析
Dec 09 Python
Python scrapy增量爬取实例及实现过程解析
Dec 24 Python
Python通过4种方式实现进程数据通信
Mar 12 Python
简单了解python调用其他脚本方法实例
Mar 26 Python
Python多线程正确用法实例解析
May 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实现的功能是显示8条基色色带
2006/10/09 PHP
PHP定时执行计划任务的多种方法小结
2011/12/19 PHP
简单的php新闻发布系统教程
2014/05/09 PHP
[原创]php逐行读取txt文件写入数组的方法
2015/07/02 PHP
php邮件发送的两种方式
2020/04/28 PHP
浅析PHP数据导出知识点
2018/02/17 PHP
PHP将整数数字转换为罗马数字实例分享
2019/03/17 PHP
php中加密解密DES类的简单使用方法示例
2020/03/26 PHP
让您的菜单不离网站
2006/10/03 Javascript
不错的JS中变量相关的细节分析
2007/08/13 Javascript
JS模板实现方法
2013/04/03 Javascript
JS获取各种浏览器窗口大小的方法
2014/01/14 Javascript
JavaScript使用循环和分割来替换和删除元素实例
2014/10/13 Javascript
jQuery不使用插件及swf实现无刷新文件上传
2014/12/08 Javascript
Javascript 调用 ActionScript 的简单方法
2016/09/22 Javascript
jQuery 1.9版本以上的浏览器判断方法代码分享
2017/08/28 jQuery
JS如何设置元素样式的方法示例
2017/08/28 Javascript
js链表操作(实例讲解)
2017/08/29 Javascript
js前端导出Excel的方法
2017/11/01 Javascript
JavaScript使用闭包模仿块级作用域操作示例
2019/01/21 Javascript
JS localStorage存储对象,sessionStorage存储数组对象操作示例
2020/02/15 Javascript
[02:40]DOTA2殁境神蚀者 英雄基础教程
2013/11/26 DOTA
老生常谈Python之装饰器、迭代器和生成器
2017/07/26 Python
python3+opencv3识别图片中的物体并截取的方法
2018/12/05 Python
python 缺失值处理的方法(Imputation)
2019/07/02 Python
基于梯度爆炸的解决方法:clip gradient
2020/02/04 Python
tensorflow之自定义神经网络层实例
2020/02/07 Python
浅析CSS3 用text-overflow解决文字排版问题
2020/10/28 HTML / CSS
丝芙兰巴西官方商城:SEPHORA巴西
2016/10/31 全球购物
战友聚会邀请函
2014/01/18 职场文书
小学教师听课制度
2014/02/01 职场文书
入股协议书
2014/04/14 职场文书
物理分数没达标检讨书
2014/09/13 职场文书
2015初中生物教研组工作总结
2015/07/21 职场文书
Apache Pulsar结合Hudi构建Lakehouse方案分析
2022/03/31 Servers
SQLyog的下载、安装、破解、配置教程(MySQL可视化工具安装)
2022/09/23 MySQL