日志監控是企業監控系統裡面很重要的一個環節,通過日志監控可以提前發現網絡裝置或者系統存在的未知或者潛在的風險,讓運維人員及時幹預,減少損失。常見的監控系統Zabbix、Prometheus都支援日志的監控。但由于在資料量、搜尋、可視化、報警等方面都比較弱化,推薦使用專業的日志收集與告警工具ELK或者Graylog。下面通過Graylog實作系統日志的采集、分析、報表的展示和告警,為廣大網友提供一個思路,其它的如業務日志、MySQL錯誤日志、網絡裝置的日志、微服務的日志都是一個道理,要學會舉一反三。
一、Rsyslog安裝配置
1.1 Rsyslog 服務端的配置,IP為 192.168.10.100。
yum install -y rsyslog
vim /etc/rsyslog.conf
# 通過UDP協調 514 端口接收日志
$ModLoad imudp.so
$UDPServerRun 514
# 通過TCP協定 1515 端口接收日志
$ModLoad imtcp.so
$InputTCPServerRun 1515
# 重新開機服務
systemctl restart rsyslog
1.2 Rsyslog用戶端的配置。
通過TCP協定把日志傳輸給Rsyslog Server伺服器上面。
vim /etc/rsyslog.conf
#使用TCP協定,一個@表示UDP協定,兩個@表示TCP協定,預設端口不需要加端口,自定義的需要加端口。
# *.* @192.168.10.100
#使用TCP協定
*.* @@192.168.10.100:1515
systemctl restart rsyslog
1.3 Rsyslog日志級别。
Rsyslog 日志級别總共有7種,數字代号為0-7,數字越小,代表級别越高。預設收集的rsyslog沒有記錄日志的級别,在Rsyslog Server上面通過模闆的方式讓把日志的級别記錄到日志裡面,友善後期告警。
none 不算是一個等級,它表示不記錄服務的所有資訊
0 emerg 系統不可用
1 alert 特别留意的報警資訊
2 crit 非常嚴重的狀況
3 err 錯誤資訊
4 warning 警告資訊
5 notice 稍微要注意的資訊
6 info 正常資訊
7 debug 調試資訊,開發人員使用
$template GRAYLOGSYSLOG,"%timegenerated% %HOSTNAME% %fromhost-ip% %syslogtag%%msg% %syslogseverity%\n"
$ActionFileDefaultTemplate GRAYLOGSYSLOG
#本地儲存日志
$template Remote,"/data/logs/linux/%FROMHOST-IP%/%FROMHOST-IP%.log" *
*.* @@192.168.10.100:1515;GRAYLOGSYSLOG
二、通過Graylog收集系統日志
通過Graylog的System/Inputs建立一個類型為Syslog TCP的 INPUT,端口為1515。然後通過INPUT的 Show received messages就可以看到收集過來的日志,日志最後的數字代表系統日志的級别,即我們模闆裡面配置的syslogseverity。

三、Graylog 郵件告警
Graylog 告警的流程大概是日志通過INPU進入系統,然後通過Streams過濾需要告警的關鍵字(可以通過message過濾關鍵字、通過日志級别告警),最後通過Alert定義告警的條件和需要接收的告警人。
3.1 開啟Graylog郵件報警功能。
修改graylog配置檔案,開啟Graylog發郵件的功能,通過系統自帶的postfix就可以發送郵件告警。
# Email transport
transport_email_enabled = true
transport_email_hostname = 192.168.10.100
transport_email_port = 25
transport_email_use_auth = false
transport_email_subject_prefix = [graylog]
transport_email_from_email = [email protected]
#重新開機服務
[root@graylog-server ~]# /etc/init.d/graylogctl start
3.2 建立Stream。
Stream用于過濾需要告警的日志,可以通過Fields過濾或者通過關鍵字過濾,其它選型選擇預設即可。
3.3 定義Rsyslog日志格式。
雖然我們在收集日志的時候定義了日志的級别,但graylog需要通過Fields提取日志的級别。通過INPUT,點選Manae extractors 建立提取器。通過Load Message 選擇一條日志,在通過Regular expression正則的方式比對Fields。Add Converter是為了把日志級别轉換成數字,友善統計分析。
3.4 通過Streams添加告警規則。
在Streams點選Manage Rules,建立告警日志的規則。即系統日志基本為0或者1,或者出現OOM等關鍵字的時候告警。
3.5 設定告警Alerts。
首先建立通過Alerts->Notifications建立Notification。
其次通過Alerts->Event Definition 建立Event,并關聯Streams,在Noitification關聯上面建立的Notification即可。
3.6 郵件告警測試。
當系統出現日志級别高的錯誤是會觸發告警,下面是郵件告警的内容。
192.168.20.244 Mar 20 18:29:42 ZBXDB51 kernel: journal commit I/O error 0
192.168.20.244 Mar 20 18:29:42 ZBXDB51 kernel: journal commit I/O error 0
192.168.20.244 Mar 20 18:29:42 ZBXDB51 kernel: journal commit I/O error 0
192.168.20.244 Mar 20 18:29:42 ZBXDB51 kernel: journal commit I/O error 0
四、Graylog微信告警
因為系統的日志的級别為0-1,相對于系統來講,已經出現很嚴重的問題,需要運維人員立即确認處理。是以需要通過微信或者短信的方式通知相關人員。Graylog有豐富完善的API接口,Graylog Api接口:System/Nodes ->Nodes->API browser。通過下面接口用Python構造程式,通過定時任務進而實作微信告警。
[root@graylog-server ~]# cat /zabbix/python/graylog/getgrayloglinuxsystemlogsalert.py
#!/usr/bin/env python
#_*_coding:utf-8 _*_
#樸實的追夢者
import os
import sys
import json
import time
import MySQLdb
import requests
import datetime
import simplejson
reload(sys)
sys.setdefaultencoding('utf-8')
startTime = ( datetime.datetime.now() - datetime.timedelta(seconds=600)).strftime('%Y-%m-%d %H:%M:%S')
endTime = (datetime.datetime.now()).strftime('%Y-%m-%d %H:%M:%S')
def gettoken(corpid, corpsecret):
gettoken_url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=' + corpid + '&corpsecret=' + corpsecret
try:
token_file = requests.get(gettoken_url)
token_data = token_file.text
token_json = json.loads(token_data)
token_json.keys()
token = token_json['access_token']
#print (token)
return token
except requests.RequestException as e:
print(e)
def senddata(access_token, user, msg_type, **msg_dic):
send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + access_token
send_values = {
#"touser":user,
"toparty": user,
"msgtype": msg_type,
"agentid": "xxxxxx",
"safe": "0"
}
for k,v in msg_dic.items():
send_values[msg_type] = {k:v}
print send_values
send_data = simplejson.dumps(send_values, ensure_ascii=False).encode('utf-8')
send_request = requests.post(send_url, send_data)
print(send_request)
response = json.loads(send_request.text)
print str(response)
def getmediaid(token):
url = 'https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=' + token + '&type=file'
files = {'file': open(filename)}
r = requests.post(url, files=files)
re = json.loads(r.text)
return re['media_id']
def getGraylogMessage():
url = 'http://192.168.10.100:8080/api/search/universal/absolute'
headers = {
'Content-Type': "application/json",
'user-agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"
}
data = {
# 通過Graylog 查詢文法
"query": "rsyslogs_level:<=1",
#"from": "2021-06-24 00:00:00",
"from": startTime,
#"to": "2021-06-25 10:00:00",
"to": endTime,
"limit": "10",
"decorate": "true",
}
res = requests.get(url, params=data, headers=headers, auth=('admin', 'xxxxxx'))
print res.status_code
try:
list = res.json()['messages']
except KeyError as e:
print "No json Object could be decoded."
return list
if __name__ == '__main__':
list = getGraylogMessage()
filename = "/zabbix/python/graylog/logs/graylogLinuxOsErr.txt"
corpid = 'xxxxxx'
corpsecret = 'xxxxxx'
accesstoken = gettoken(corpid, corpsecret)
if os.path.exists(filename):
os.remove(filename)
print len(list)
# 日志數量小于等于2的時候通過消息告警
if len(list) != 0 and len(list) <=2:
for line in list:
content = "[graylog] %s %s Logs Level:%d\n" % (line['message']['ip'],line['message']['message'],line['message']['rsyslogs_level'])
print content
msg_dic = {"content" : content}
senddata(accesstoken,2,'text',**msg_dic)
# 日志數量大于2條的時候通過推送檔案方式告警
elif len(list) != 0 and len(list) >2:
for line in list:
content = "[graylog] %s %s Logs Level:%d\n" % (line['message']['ip'],line['message']['message'],line['message']['rsyslogs_level'])
with open(filename, 'a') as f:
f.write(content + '\n')
msg_dic = {"media_id" : getmediaid(accesstoken)}
senddata(accesstoken,8,'file',**msg_dic)