使用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)
]]

这个时候解析起来就相对复杂,我们可以使用如下脚本来取得最近五分钟的日志:

  1. #!/bin/bash
  2.  
  3. # 取得前5分钟时间
  4. LAST_MINUTE=$(date -d '-5 minute' +%H%M%S)
  5. # 初始化日志条数
  6. LOG_NUM=0
  7. # 最大获取日志条数
  8. MAX_LOG=3
  9. # 初始化最终匹配日志
  10. LOG_CONTENT=""
  11. # 初始化包含时间行的匹配值
  12. LOG_DATE_MATCH=false
  13. # 设置日志路径
  14. LOG_PATH="/data/log/glassfish/domain1/server.log"
  15.  
  16. while read line;do
  17.  
  18.      # 匹配包含时间的行
  19.      if echo "$line" | grep -q '^\[20';then
  20.           # 根据包含时间行获取出特定时间格式,如181320
  21.           date_time=$(echo $line | grep -E -o "[0-9]{2}:[0-9]{2}:[0-9]{2}" | tr -d ':')
  22.  
  23.           date_time=$(echo $date_time | sed 's/^0//')
  24.           LAST_MINUTES=$(echo $LAST_MINUTES | sed 's/^0//')
  25.           # 当前行的时间是否大于5分钟前的时间         
  26.           if [[ "$date_time" -gt "$LAST_MINUTE" ]];then
  27.                LOG_CONTENT="$LOG_CONTENT\n$log_entry"
  28.                ((LOG_NUM++))
  29.                LOG_DATE_MATCH=true
  30.                log_entry="$line\n"
  31.           else
  32.                LOG_DATE_MATCH=false
  33.                continue
  34.           fi
  35.  
  36.      else
  37.           # 只当前面日志时间满足条件时才设置log_entry值
  38.           if $LOG_DATE_MATCH;then
  39.                log_entry="$log_entry\n$line"
  40.           fi   
  41.      fi
  42.  
  43.      # 限制最大获取行数
  44.      if [[ "$LOG_NUM" -gt "$MAX_LOG" ]];then
  45.           break
  46.      fi
  47.  
  48. done < $LOG_PATH
  49.  
  50. # 输出全部日志
  51. echo -n -e "$LOG_CONTENT"

前面的脚本按顺序读取的,但当日志文件比较大时,获取日志的效率就非常低了,所以推荐下面倒序读取日志的方法,更高效。

  1. #!/bin/bash
  2.  
  3. # 取得前5分钟时间
  4. LAST_MINUTE=$(date -d '-5 minute' +%H%M%S)
  5. # 初始化日志条数
  6. LOG_NUM=0
  7. # 最大获取日志条数
  8. MAX_LOG=3
  9. # 初始化最终匹配日志
  10. LOG_CONTENT=""
  11. # 设置日志路径
  12. LOG_PATH="/data/log/glassfish/domain1/server.log"
  13.  
  14. while read line;do
  15.  
  16.      # 匹配包含时间的行
  17.      if echo "$line" | grep -q '^\[20';then
  18.           # 根据包含时间行获取出特定时间格式,如181320
  19.           date_time=$(echo $line | grep -E -o "[0-9]{2}:[0-9]{2}:[0-9]{2}" | tr -d ':')
  20.         
  21.           # 当前行的时间是否大于5分钟前的时间   
  22.           if [[ "$date_time" > "$LAST_MINUTE" ]];then
  23.                ((LOG_NUM++))
  24.                log_entry="$line\n$log_entry"
  25.                LOG_CONTENT="$LOG_CONTENT\n$log_entry"
  26.           else
  27.                break
  28.           fi
  29.  
  30.           log_entry=""
  31.  
  32.      else
  33.           log_entry="$line\n$log_entry"
  34.      fi
  35.  
  36.      # 限制最大获取行数
  37.      if [[ "$LOG_NUM" > "$MAX_LOG" ]];then
  38.           break
  39.      fi
  40.  
  41. done < <(tac $LOG_PATH)
  42.  
  43. # 输出全部日志
  44. echo -n -e "$LOG_CONTENT"

之后就可以在zabbix添加一个监控项用来获取日志内容,触发器就使用{itemName.strlen(0)}#0表达式来检测获取到的日志内容是否不为空。itemName为监控项名称。

标签:Zabbix监控 发布于:2019-11-22 00:36:39