使用zabbix根据时间监控多行格式的日志
我们目前想使用zabbix每五分钟监控一个错误日志文件,如果监控到有错误产生,就发邮件告警。像标准的访问日志,如nginx的access log,一行表示一条日志,解析起来比较容易,但当日志不是一行一条时,如tomcat,glassfish的日志,如下:
[2015-07-17T14:24:04.552+0800] [glassfish 4.0] [SEVERE] [AS-WEB-CORE-00037] [javax.enterprise.web.core] [tid: _ThreadID=26 _ThreadName=http-listener-1(3)] [timeMillis: 1437114244552] [levelValue: 1000] [[
An exception or error occurred in the container during the request processing
java.lang.IllegalArgumentException
at org.glassfish.grizzly.http.util.CookieParserUtils.parseClientCookies(CookieParserUtils.java:353)
at org.glassfish.grizzly.http.util.CookieParserUtils.parseClientCookies(CookieParserUtils.java:336)
at org.glassfish.grizzly.http.Cookies.processClientCookies(Cookies.java:220)
at org.glassfish.grizzly.http.Cookies.get(Cookies.java:131)
at org.glassfish.grizzly.http.server.Request.parseCookies(Request.java:1911)
at org.glassfish.grizzly.http.server.Request.getCookies(Request.java:1505)
at org.apache.catalina.connector.Request.parseSessionCookiesId(Request.java:4077)
at org.apache.catalina.connector.CoyoteAdapter.postParseRequest(CoyoteAdapter.java:649)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:297)
]]
这个时候解析起来就相对复杂,我们可以使用如下脚本来取得最近五分钟的日志:
- #!/bin/bash
- # 取得前5分钟时间
- LAST_MINUTE=$(date -d '-5 minute' +%H%M%S)
- # 初始化日志条数
- LOG_NUM=0
- # 最大获取日志条数
- MAX_LOG=3
- # 初始化最终匹配日志
- LOG_CONTENT=""
- # 初始化包含时间行的匹配值
- LOG_DATE_MATCH=false
- # 设置日志路径
- LOG_PATH="/data/log/glassfish/domain1/server.log"
- while read line;do
- # 匹配包含时间的行
- if echo "$line" | grep -q '^\[20';then
- # 根据包含时间行获取出特定时间格式,如181320
- date_time=$(echo $line | grep -E -o "[0-9]{2}:[0-9]{2}:[0-9]{2}" | tr -d ':')
- date_time=$(echo $date_time | sed 's/^0//')
- LAST_MINUTES=$(echo $LAST_MINUTES | sed 's/^0//')
- # 当前行的时间是否大于5分钟前的时间
- if [[ "$date_time" -gt "$LAST_MINUTE" ]];then
- LOG_CONTENT="$LOG_CONTENT\n$log_entry"
- ((LOG_NUM++))
- LOG_DATE_MATCH=true
- log_entry="$line\n"
- else
- LOG_DATE_MATCH=false
- continue
- fi
- else
- # 只当前面日志时间满足条件时才设置log_entry值
- if $LOG_DATE_MATCH;then
- log_entry="$log_entry\n$line"
- fi
- fi
- # 限制最大获取行数
- if [[ "$LOG_NUM" -gt "$MAX_LOG" ]];then
- break
- fi
- done < $LOG_PATH
- # 输出全部日志
- echo -n -e "$LOG_CONTENT"
前面的脚本按顺序读取的,但当日志文件比较大时,获取日志的效率就非常低了,所以推荐下面倒序读取日志的方法,更高效。
- #!/bin/bash
- # 取得前5分钟时间
- LAST_MINUTE=$(date -d '-5 minute' +%H%M%S)
- # 初始化日志条数
- LOG_NUM=0
- # 最大获取日志条数
- MAX_LOG=3
- # 初始化最终匹配日志
- LOG_CONTENT=""
- # 设置日志路径
- LOG_PATH="/data/log/glassfish/domain1/server.log"
- while read line;do
- # 匹配包含时间的行
- if echo "$line" | grep -q '^\[20';then
- # 根据包含时间行获取出特定时间格式,如181320
- date_time=$(echo $line | grep -E -o "[0-9]{2}:[0-9]{2}:[0-9]{2}" | tr -d ':')
- # 当前行的时间是否大于5分钟前的时间
- if [[ "$date_time" > "$LAST_MINUTE" ]];then
- ((LOG_NUM++))
- log_entry="$line\n$log_entry"
- LOG_CONTENT="$LOG_CONTENT\n$log_entry"
- else
- break
- fi
- log_entry=""
- else
- log_entry="$line\n$log_entry"
- fi
- # 限制最大获取行数
- if [[ "$LOG_NUM" > "$MAX_LOG" ]];then
- break
- fi
- done < <(tac $LOG_PATH)
- # 输出全部日志
- echo -n -e "$LOG_CONTENT"
之后就可以在zabbix添加一个监控项用来获取日志内容,触发器就使用{itemName.strlen(0)}#0表达式来检测获取到的日志内容是否不为空。itemName为监控项名称。
目录 返回
首页