python 실시 간 분석 로그 의 작은 스 크 립 트 공유

머리말
웹 운영 은 관련 도 메 인 이름 의 실시 간 2xx/s,4xx/s,5xx/s,응답 시간,대역 폭 등 지 표를 주목 해 야 한 다 는 것 을 잘 알 고 있 습 니 다.이전 로 그 는 5 분 에 한 번 씩 분할 되 었 고 간단하게 awk 를 사용 하면 됩 니 다.지금 은 로 그 를 ELK 로 전송 해 야 하기 때문에 5 분 동안 분할 하 는 데 문제 가 있 으 면 하루 에 한 번 씩 분할 하 는 것 으로 바 꾸 었 습 니 다.하루 에 한 번 씩 분할 한 후에 분명히 Shell 을 계속 사용 하 는 것 은 적합 하지 않 아서 Python 으로 썼 다.
방법 은 다음 과 같다.
스 크 립 트 는 주로 파일 의 seek 와 tell 함 수 를 사 용 했 습 니 다.원 리 는 다음 과 같 습 니 다.
       1.crontab 가입,5 분 마다 실행
       2.마지막 으로 읽 은 로그 파일 의 끝 위치 부터 이번 파일 을 읽 을 때의 끝 위치 사이 의 로그 만 분석 하여 결 과 를 냅 니 다.
zabbix 사용 가능sender 는 결 과 를 zabbix server 에 보 내 거나 zabbix 에이전트 를 사용 하여 이 파일 을 읽 고 데 이 터 를 가 져 옵 니 다.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
' % start_position) fh.write('end_position: %s
' % 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
' % start_position) fh.write('end_position: %s
' % 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
status_403: %s
status_404: %s
status_500: %s
status_502: %s
status_503: %s
status_504: %s
status_all: %s
rt: %s
bandwidth: %s
" % (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
status_403: %s
status_404: %s
status_500: %s
status_502: %s
status_503: %s
status_504: %s
status_all: %s
rt: %s
bandwidth: %s
" % (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
나중에 문제 가 좀 생 겼 어 요.startposition、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)
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기