Shell脚本实战:日志关键字监控+自动告警

系统 Linux
主要用于Linux服务器监控程序日志,如出现关键字异常则触发相应的动作或告警操作,通知到邮件联系人。

该程序使用场景说明:主要用于Linux服务器监控程序日志,如出现关键字异常则触发相应的动作或告警操作,通知到邮件联系人。

一、安装邮件服务

1、解压 

  1. tar -jxf mailx-12.4.tar.bz2 -C /usr/src/ && cd /usr/src/mailx-12.4/ 

2、编译 

  1. make install UCBINSTALL=/usr/bin/install 

异常编译报错-1

异常报错解决方法

下载mailx补丁文件“mailx-12.4-openssl_1.0.0_build_fix-1.patch”,将补丁文件和mailx解压缩目录放置同一路径

执行打补丁命令: 

  1. patch -p0 < mailx-12.4-openssl_1.0.0_build_fix-1.patch 

进入mailx-12.4重新执行编译命令: 

  1. make install UCBINSTALL=/usr/bin/install 

检测mailx是否安装成功:mailx -V

3、配置 

vi /etc/nail.rc,在文件的最后添加

set from=

set smtp=

set smtp-auth-user=

set smtp-auth-password=

set smtp-auth=login

如下图所示,修改配置完后保存

4、测试发送邮件

echo '邮件正文'|mailx -v -s "邮件标题" 邮箱地址

至此邮件功能测试正常,接下来是关键字监控脚本的编写工作,通过日志关键字脚本触发邮件告警脚本实现日志监控

二、关键字监控脚本开发

CheckLogs.sh 日志监控程序

SendMail.sh 发邮件脚本,该脚本可自定义

conf 配置文件目录,chklist为配置文件

初次执行CheckLogs.sh脚本会读取日志文件并记录当前读取的行数

后续运行脚本则读取更新日志,例如当前日志更新了9行数据,则脚本从最新的9行数据获取关键字

测试插入关键字error

继续执行脚本可以看到已捕获关键字并触发告警

测试多关键字

再次执行可以看到已捕获最新更新的日志信息

测试频率控制

至此相关功能测试已完成。最后附上脚本相关代码如下: 

  1. #!/bin/bash  
  2. basedir=$(cd `dirname "$0"`;pwd)  
  3. logsdir=$basedir/logs  
  4. tmpsdir=$basedir/tmps  
  5. confdir=$basedir/conf  
  6. chkfile=$confdir/chklist  
  7. logfile=$logsdir/log.log_$(date +%F)  
  8. #创建各种目录  
  9. mkdir -p $logsdir $tmpsdir $confdir  
  10. #创建配置文件  
  11. if test ! -e "$chkfile";then  
  12.     echo "#日志文件,关键字(多关键字|隔开),重试次数,最大执行次数,启动命令,停止命令" >$chkfile  
  13. fi  
  14. #生成日志函数  
  15. do_writelog() {  
  16.     case $1 in  
  17.     i|I)  
  18.         shift  
  19.         echo "$(date +%Y-%m-%d) $(date +%H:%M:%S)|INFO|$@" >>$logfile  
  20.         ;;  
  21.     e|E)  
  22.         shift  
  23.         echo "$(date +%Y-%m-%d) $(date +%H:%M:%S)|ERROR|$@" >>$logfile  
  24.         ;;  
  25.     w|W)  
  26.         shift  
  27.         echo "$(date +%Y-%m-%d) $(date +%H:%M:%S)|WARNING|$@" >>$logfile  
  28.         ;;  
  29.     *)  
  30.         echo "$(date +%Y-%m-%d) $(date +%H:%M:%S)|DEBUG|$@" >>$logfile  
  31.         esac  
  32.  
  33. #日志处理部分代码  
  34. cat $chkfile|egrep -v "^($|#)"|while read i;do  
  35.  
  36.     app_name=$(echo "$i"|awk -F, '{print $1}')  
  37.     if test -z "$app_name";then  
  38.         do_writelog e "应用名称为空,退出执行"  
  39.         exit 0  
  40.     fi  
  41.     log_filename=$(echo "$i"|awk -F, '{print $2}')  
  42.     if test ! -e "$log_filename";then  
  43.         do_writelog e "日志文件($log_filename)不存在,退出执行"  
  44.         exit 0  
  45.     fi  
  46.     log_md5sum=$(echo -n "$log_filename"|md5sum|awk '{print $1}')  
  47.     log_gjz=$(echo "$i"|awk -F, '{print $3}')  
  48.     if test -z "$log_gjz";then  
  49.         do_writelog i "日志文件($log_filename),关键字为空,退出执行"  
  50.         exit 0  
  51.     fi  
  52.     log_retry=$(echo "$i"|awk -F, '{print $4}')  
  53.     expr $log_retry + 0 &>/dev/null  
  54.     if [ $? -ne 0 ];then  
  55.         log_retry=0  
  56.     fi 
  57.      log_max=$(echo "$i"|awk -F, '{print $5}')  
  58.     expr $log_max + 0 &>/dev/null  
  59.     if [ $? -ne 0 ];then  
  60.         log_max=3  
  61.     fi  
  62.     start_command=$(echo "$i"|awk -F, '{print $6}')  
  63.     stops_command=$(echo "$i"|awk -F, '{print $7}')  
  64.     open_sendmail=$(echo "$i"|awk -F, '{print $8}')  
  65.     mail_scripts=$(echo "$i"|awk -F, '{print $9}')  
  66.     mail_contacts=$(echo "$i"|awk -F, '{print $10}')  
  67.     if [ $open_sendmail -eq 1 ];then  
  68.         if test -z "$mail_scripts";then  
  69.             do_writelog i "应用($app_name),触发动作脚本为空,退出执行"  
  70.             exit 0  
  71.         fi  
  72.         if test -z "$mail_contacts";then  
  73.             do_writelog i "应用($app_name),联系人为空,退出执行"  
  74.             exit 0  
  75.         fi  
  76.     fi  
  77.     if test ! -e "$tmpsdir/$log_md5sum";then  
  78.         log_new_count=$(wc -l $log_filename|awk '{print $1}')  
  79.         echo "$log_new_count" >$tmpsdir/$log_md5sum 
  80.         do_writelog i "日志文件($log_filename),初始化读取日志行数:$log_new_count,退出执行"  
  81.     else  
  82.         log_old_count=$(cat $tmpsdir/$log_md5sum)  
  83.         expr $log_old_count + 0 &>/dev/null 
  84.          if [ $? -ne 0 ];then  
  85.             do_writelog e "日志文件($log_filename),读取历史行数失败,退出执行"  
  86.             exit 0  
  87.         fi  
  88.         log_new_count=$(wc -l $log_filename|awk '{print $1}')  
  89.         if [ $log_new_count -eq $log_old_count ];then  
  90.             do_writelog i "日志文件($log_filename),未更新,退出执行"  
  91.             exit 0  
  92.         elif [ $log_new_count -lt $log_old_count ];then  
  93.             do_writelog i "日志文件($log_filename),跨日更新日志行数:$log_new_count,退出执行"  
  94.             echo "$log_new_count" >$tmpsdir/$log_md5sum  
  95.         else  
  96.            log_upd_count=$(expr $log_new_count - $log_old_count)  
  97.            do_writelog i "日志文件($log_filename),历史行数:$log_old_count,最新行数:$log_new_count,更新行数:$log_upd_count"   
  98.            #读取更新的日志  
  99.            log_content=$(tail -n +`expr $log_old_count + 1` $log_filename|head -n +$log_upd_count)  
  100.            oldIFS=$IFS  
  101.            IFS="|"  
  102.            count=0  
  103.            for i in $log_gjz;do  
  104.                if [ $(echo "$log_content"|grep -c -w "$i") -ge 1 ];then  
  105.                    let count+=1    
  106.                fi  
  107.                if [ $count -gt 0 ];then  
  108.                    break  
  109.                fi  
  110.            done  
  111.            IFS=$oldIFS  
  112.            if [ $count -gt 0 ];then  
  113.                echo "0" >>$tmpsdir/${log_md5sum}.retry  
  114.            else  
  115.               do_writelog i "日志文件($log_filename),未获取到关键字,退出执行"  
  116.               echo "$log_new_count" >$tmpsdir/$log_md5sum  
  117.               exit 0  
  118.            fi  
  119.            if [[ $(wc -l $tmpsdir/${log_md5sum}.retry|awk '{print $1}') -gt $log_retry ]];then  
  120.                echo "0" >>$tmpsdir/${log_md5sum}_$(date +%F)  
  121.                if [ $(wc -l $tmpsdir/${log_md5sum}_$(date +%F)|awk '{print $1}') -le $log_max ];then  
  122.                    $stops_command 1>>$logfile 2>&1  
  123.                    $start_command 1>>$logfile 2>&1  
  124.                    do_writelog i "日志文件($log_filename),日志内容:$log_content,找到关键字:$i,停止命令:$stops_command,启动命令:$start_command,重启服务"  
  125.                    if [ $open_sendmail -eq 1 ];then  
  126.                        if test -n "$mail_scripts";then  
  127.                            $mail_scripts "应用[$app_name]故障" "日志文件($log_filename),日志内容:$log_content,找到关键字:$i" "$mail_contacts" 1>>$logfile 2>&1  
  128.                            if [ $? -ne 0 ];then  
  129.                                do_writelog i "日志文件($log_filename),日志内容:$log_content,找到关键字:$i,触发告警失败"  
  130.                            fi  
  131.                            do_writelog i "日志文件($log_filename),日志内容:$log_content,找到关键字:$i,触发告警通知联系人:[$mail_contacts]"  
  132.                        fi  
  133.                    else  
  134.                        do_writelog i "日志文件($log_filename),日志内容:$log_content,找到关键字:$i,不触发告警"  
  135.                    fi  
  136.                else  
  137.                    do_writelog i "日志文件($log_filename),日志内容:$log_content,找到关键字:$i,重启服务超出当天限制次数:$log_max,退出执行"  
  138.                fi  
  139.                rm -f $tmpsdir/${log_md5sum}.retry &>/dev/null  
  140.            else  
  141.                do_writelog i "日志文件($log_filename),日志内容:$log_content,找到关键字:$i,重试检测:$(wc -l $tmpsdir/${log_md5sum}.retry|awk '{print $1}')"  
  142.            fi  
  143.            echo "$log_new_count" >$tmpsdir/$log_md5sum  
  144.            do_writelog i "日志文件($log_filename),更新记次文件完成"   
  145.         fi  
  146.     fi  
  147. )&  
  148. done 

 

 

责任编辑:庞桂玉 来源: Linux学习
相关推荐

2009-11-26 19:24:54

PHP类CMS

2022-01-04 16:35:42

C++Protected关键字

2009-09-02 09:24:03

C# this关键字

2012-03-01 12:50:03

Java

2009-09-17 09:30:00

Linq LET关键字

2018-04-20 15:56:09

Pythonglobal关键字

2009-08-21 14:58:56

C# this关键字

2013-01-30 10:12:14

Pythonyield

2022-06-29 08:05:25

Volatile关键字类型

2009-08-13 13:04:29

C# lock关键字

2022-05-06 08:32:40

Pythonwith代码

2021-02-01 13:10:07

Staticc语言UNIX系统

2022-02-17 08:31:38

C语言staic关键字

2019-11-06 10:36:43

MavenoptionalJava

2021-08-06 07:51:47

关键字int函数

2019-12-20 15:19:41

Synchroinze线程安全

2009-08-26 15:16:29

C# lock关键字

2009-08-06 17:52:23

C#增加that关键字

2009-08-13 17:44:34

C# using关键字

2009-08-21 14:47:59

C# base关键字
点赞
收藏

51CTO技术栈公众号