侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

python实时分析日志的一个小脚本分享

Python  /  管理员 发布于 7年前   213

前言

大家都知道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-8from __future__ import divisionimport osLOG_FILE = '/data0/logs/nginx/xxxx-access_log'POSITION_FILE = '/tmp/position.log'STATUS_FILE = '/tmp/http_status'#crontab 执行时间CRON_TIME = 300def 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_statusstatus_2xx: 17.3333333333status_403: 0.0status_404: 1.0status_500: 0.0status_502: 0.0status_503: 0.0status_504: 0.0status_all: 20.0rt: 0.0782833333333bandwidth: 204032.0

后来发现有点问题,start_position、end_position 使用字符串比较会有问题,如下:

In [5]: '99772400' > '100227572'Out[5]: TrueIn [6]: int('99772400') > int('100227572')Out[6]: False

因此,更正为:

#日志轮转导致start_position > end_position#print start_position,end_positionif int(start_position) > int(end_position): start_position = 0#日志停止滚动时elif int(start_position) == int(end_position): os._exit(1)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家的支持。


  • 上一条:
    python生成式的send()方法(详解)
    下一条:
    python分割列表(list)的方法示例
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go语言中实现字符串可逆性压缩及解压缩功能(0个评论)
    • 使用go + gin + jwt + qrcode实现网站生成登录二维码在app中扫码登录功能(0个评论)
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客