最近开发人员提了一个新的监控需求,当一个日志文件中出现的错误的次数增加时(日志文件中的错误关键字出现数量增加)则触发报警。
我觉得这是一个无聊的问题,问题之所以无聊,是因为该问题本身就具有局限性(自己给自己挖坑)。首先,日志文件不可能无穷的增大,因此当日志文件因为人为维护时发生的任何变化必会触发报警;
其次,通过检测错误关键字或者错误代码的方法也可能不靠谱,例如日志中可能出现一些并不是错误代码但与错误代码相同的数字,因此错误关键字和错误代码需要同时监测;
再如产生日志的进程的重新启动或者挂起,日志切割(logrotate)等都会导致存储的计数发生变化,很多情况都会触发虚假报警,因此这个问题真的很无聊!
并不是说要检测到这个错误的次数真的很复杂(实际也确实不简单),如果要检测是否有问题大可不必这样做,对于程序而言,所有影响程序正确执行的任何问题全都是异常,只要异常被捕获并被正确处理势必可以清晰的知道问题出在哪里,该如何解决。因此设计初期如果不提前做好这些打算,日后处理起来只能以无聊来讽刺了。
废话不说了,有两个方法可以简易实现,在此贴一下。
方法1:写两个脚本,一个持续运行,一个供监控软件运行,其中持续运行的脚本可以由crontab来做,供监控软件运行的命令行和脚本无论逻辑有多复杂流程有多少条必须具有退出运行的处理。
方法2:利用监控软件自带的diff或change,变化趋势由监控软件判断(以zabbix为例),zabbix的trigger的表达式能轻松的将采集到数据以各种表达式计算出用户想要的数据,省却了用户自己编写程序或脚本解决文字比较、数字计算和趋势计算等较为复杂的问题。
方法1:getdata.sh在后台运行用来提供数据,checkdata.sh给zabbix运行,用来查询数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<code>#!/bin/bash</code>
<code># name: getdata.sh</code>
<code>javalogfile=</code><code>/data/tomcat/tomcat-cstest/logs/catalina</code><code>.out</code>
<code>pathtojavalogfile=$(</code><code>dirname</code> <code>$javalogfile)</code>
<code>zabbixstatusfile=pathtojavalogfile/.zabbixstatus.catalina.out</code>
<code>errorkeyword=13003</code>
<code>previoustime=$(</code><code>grep</code> <code>"$errorkeyword"</code> <code>$javalogfile | </code><code>wc</code> <code>-l)</code>
<code>currenttime=$(</code><code>grep</code> <code>"$errorkeyword"</code> <code>$javalogfile | </code><code>wc</code> <code>-l)</code>
<code>if</code> <code>[[ ! $previoustime -</code><code>eq</code> <code>$currenttime ]]; </code><code>then</code>
<code> </code><code>echo</code> <code>0</code>
<code> </code><code>exit</code> <code>1</code>
<code>fi</code>
<code>while</code> <code>[[ $previoustime -</code><code>eq</code> <code>$currenttime ]]; </code><code>do</code>
<code> </code><code># 其实此处就像crontab,while+sleep=crontab</code>
<code> </code><code>sleep</code> <code>2</code>
<code> </code><code>currenttime=$(</code><code>grep</code> <code>"$errorkeyword"</code> <code>$javalogfile | </code><code>wc</code> <code>-l)</code>
<code> </code><code>if</code> <code>[[ $currenttime -gt $previoustime ]]; </code><code>then</code>
<code> </code><code>previoustime=$currenttime</code>
<code> </code><code>echo</code> <code>0 >>$zabbixstatusfile</code>
<code> </code><code>elif</code> <code>[[ $currenttime -</code><code>le</code> <code>$previoustime ]]; </code><code>then</code>
<code> </code><code>echo</code> <code>1 >>$zabbixstatusfile</code>
<code> </code><code>fi</code>
<code>done</code>
<code># name: checkdata.sh</code>
<code>grep</code> <code>"0"</code> <code>$zabbixstatusfile</code>
<code>if</code> <code>[[ $? -</code><code>eq</code> <code>0 ]]; </code><code>then</code>
<code> </code><code>true</code> <code>> $zabbixstatusfile</code>
<code>else</code>
<code> </code><code>echo</code> <code>1</code>
<code> </code><code>exit</code> <code>0</code>
方法2:产生数据和查询数据都交给zabbix去做。
<code># single line for zabbix</code>
<code># itemname: cs connection error</code>
<code># templatenmae: template app javalogmonitor</code>
<code># applicationname: javaerrorcodetextfound</code>
<code># triggername: cs connection error is occur</code>
<code># # /etc/zabbix/zabbix_agentd.conf.d/userparameter_csconnerr.conf </code>
<code># /etc/zabbix/zabbix_agentd.conf.d/userparameter_cs.conf</code>
<code># {template app javalogmonitor:csprocess.cs.csconnerr[*].diff(0)}>0</code>
<code># for /bin/bash, such as centos</code>
<code># userparameter=csprocess.cs.csconnerr[*],javalogfile=/data/tomcat/tomcat-cstest/logs/catalina.out;errorkeyword=13003;if [[ -f $javalogfile ]]; then echo $(grep "$errorkeyword" $javalogfile | wc -l); exit 0; else echo 0; exit 1; fi</code>
<code># for /bin/sh, such as ubuntu</code>
<code>userparameter=csprocess.cs.csconnerr[*],javalogfile=</code><code>/data/tomcat/tomcat-cstest/logs/catalina</code><code>.out;errorkeyword=13003;</code><code>if</code> <code>test</code> <code>-f $javalogfile ; </code><code>then</code> <code>echo</code> <code>$(</code><code>grep</code> <code>"$errorkeyword"</code> <code>$javalogfile | </code><code>wc</code> <code>-l); </code><code>exit</code> <code>0; </code><code>else</code> <code>echo</code> <code>0; </code><code>exit</code> <code>1; </code><code>fi</code>
--end--