生產環境多臺伺服器上部署了多個應用,日誌出現報錯時,無法及時反饋到開發人員。部署一個大型的運維監控應用,不但耗資源,而且配置也不簡單。
簡簡單單寫個python指令碼來監控伺服器日誌就簡單多了,廢話不多說,直接上指令碼。
主要邏輯:
1. 使用python的subprocess模組,執行shell命令,“tail -f” 來監聽日誌檔案
2. 對輸出的日誌檔案,逐行比對字串,如果匹配到預設的字串則開始記錄,keywords中配置需要預設的異常字串
3. 開始記錄日誌至陣列中,可通過rows來預設記錄多少條,達到規定數量後
4. 將日誌內容通過http傳送給釘釘伺服器,釘釘機器人就會在群裡通知我們啦
簡單,高效,實時
#!/usr/bin/python # encoding=utf-8 # Filename: monitorLog.py import os import signal import subprocess import time import smtplib from email.mime.text import MIMEText from email.header import Header import requests import json import threading serverName="prod:192.168.100.20" #日誌檔案路徑地址 logFiles =[ "/opt/app/mall/mall-admin/logs/mall-admin-0.0.1-SNAPSHOT.log", "/opt/app/mall/mall-portal/logs/mall-portal-0.0.1-SNAPSHOT.log" ]; #機器人回撥地址 , 釘釘群裡新增一個機器人就可以了 webhook = 'https://oapi.dingtalk.com/robot/send?access_token=38670255eb92cd3a8ce94732fd785dc753134fc1c4d69141f56e942a5d453e5b' #日誌快取資料 logs = [] #記錄日誌行數,從匹配行開始記錄,到達數量就用推給釘釘機器人 rows = 2 # 是否開始記錄日誌標記位 recordFlags = [] # 檢測的關鍵字陣列,大小寫敏感 keywords = [] keywords.append("threw exception") keywords.append("java.lang.NullPointerException") keywords.append("com.macro.mall.exception.ApiRRException") keywords.append("SocketTimeoutException") #訊息內容,url地址 def dingtalk(msg,webhook): headers = {'Content-Type': 'application/json; charset=utf-8'} data = {'msgtype': 'text', 'text': {'content': msg}, 'at': {'atMobiles': [], 'isAtAll': False}} post_data = json.dumps(data) response = requests.post(webhook, headers=headers, data=post_data) return response.text # 檢查行 def checkLine(line, index): curLog = logs[index] if recordFlags[index]==1: curLog.append(line) if len(curLog)>rows: content = "\n".join('%s' %id for id in curLog) print(content) dingtalk(content,webhook) recordFlags[index] = 0 logs[index]=[] else: for keyword in keywords: if keyword in line: recordFlags[index] = 1 curLog.append(serverName) curLog.append(logFiles[index]) curLog.append(line) break #日誌檔案一般是按天產生,則通過在程式中判斷檔案的產生日期與當前時間,更換監控的日誌檔案 #程式只是簡單的示例一下,監控test1.log 10秒,轉向監控test2.log def monitorLog(logFile, index): #print('監控的日誌檔案 是%s' % logFile) popen = subprocess.Popen('tail -f ' + logFile, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) pid = popen.pid print('Popen.pid:' + str(pid)) while True: line = popen.stdout.readline().strip() # 判斷內容是否為空 if line: #print line checkLine(str(line), index) if __name__ == '__main__': for index, logFile in enumerate(logFiles): logs.append([]) recordFlags.append(0) tt = threading.Thread(target=monitorLog,args=(logFile,index)) tt.start() print ("monitor:"+str(logFile))