前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于crontab和shell实现监控告警

基于crontab和shell实现监控告警

作者头像
叔牙
发布2024-05-21 20:24:39
770
发布2024-05-21 20:24:39
举报

一、背景概述

市面上有很多开源的监控告警工具,提供了丰富的、可视化的监控指标,以及告警能力,而对于服务器维度,抛开业务指标外,我们关注的无外乎cpu使用率、内存使用率和磁盘使用率等是否超过了我们既定的安全阈值,如果超过了则推送告警通知,来引起研发人员的关注,从而采取相应的应对措施。

对于一些中小型项目,本身服务器数量并不算多,如果为了标准化和规范化再额外采购机器部署监控平台,本身会带来项目复杂度和额外的开支。

所以在项目规模不大,抑或者项目初期,用脚本来实现服务器本地化指标监控,也许是一种更好的选择。

我们大致采用服务器自身的crontab调度能力和shell脚本来实现脚本定频执行来实现监控告警:

  • 编写监控告警脚本,监控cpu、内存和磁盘(可以按需添加其他指标)使用状况
  • 如果超过设定阈值,则通过相应平台的webhook或机器人,推送告警通知
  • 通过crontab实现5s执行一次脚本,并将执行记录写入日志做滚动

二、监控脚本

创建脚本目录:

代码语言:javascript
复制
mkdir -p /opt/tools/script

创建脚本:

代码语言:javascript
复制
touch load_check.sh
chmod +x load_check.sh

脚本内容:

代码语言:javascript
复制
#!/bin/bash  
CURR_IP="xxx.xxx.xxx.xxx"
CURR_ENV="prod"
ROBOT_TOKEN="token"
THRESHOLD=80
FOCUS_PROCESS="prod-server1"
CURR_DATE=$(TZ=UTC-8 date "+%Y%m%d")
CURR_TIME=$(TZ=UTC-8 date "+%H:%M:%S")
REQ_PATH="https://open.larksuite.com/open-apis/bot/v2/hook/$ROBOT_TOKEN"
REQ_TYPE="Content-Type: application/json"


function cpu(){  
  
 util=$(vmstat | awk '{if(NR==3)print $13+$14}')  
 iowait=$(vmstat | awk '{if(NR==3)print $16}')  
 echo "${CURR_DATE} ${CURR_TIME} CPU -使用率:${util}% ,等待磁盘IO相应使用率:${iowait}:${iowait}%"  
 if [ $util -ge $THRESHOLD ]; then
    echo "cpu usage >= 80%"
    BODY="{\"msg_type\":\"interactive\",\"card\":{\"config\":{\"wide_screen_mode\":false,\"enable_forward\":true},\"elements\":[{\"tag\":\"markdown\",\"content\":\"\n**服务器名称** : $FOCUS_PROCESS \n**当前时间** : $CURR_DATE $CURR_TIME \n**服务器ip** : $CURR_IP \n**警告级别** :  CRITICAL \n**警告内容** : 当前cpu使用率 $iowait%  \n \"}],\"header\":{\"title\":{\"tag\":\"plain_text\",\"content\":\"[$CURR_ENV 环境]: 服务器预警\"},\"template\":\"red\"}}}"
      curl "$REQ_PATH" \
      -H "$REQ_TYPE" \
      -d "$BODY"
 fi
  
}  
function memory (){  
  
 total=`free -m |awk '{if(NR==2)printf "%.1f",$2/1024}'`  
    used=`free -m |awk '{if(NR==2) printf "%.1f",($2-$NF)/1024}'`  
    available=`free -m |awk '{if(NR==2) printf "%.1f",$NF/1024}'`  
    usage=$(awk "BEGIN {printf \"%.2f\", (${used}/${total})*100}")
    echo "${CURR_DATE} ${CURR_TIME} 内存 - 总大小: ${total}G , 使用: ${used}G , 剩余: ${available}G,使用率${usage}%"
    if [ $(echo "$usage >= $THRESHOLD" | bc) -eq 1 ]; then
      echo "memory usage >= 80"
      BODY="{\"msg_type\":\"interactive\",\"card\":{\"config\":{\"wide_screen_mode\":false,\"enable_forward\":true},\"elements\":[{\"tag\":\"markdown\",\"content\":\"\n**服务器名称** : $FOCUS_PROCESS \n**当前时间** : $CURR_DATE $CURR_TIME \n**服务器ip** : $CURR_IP \n**警告级别** :  CRITICAL \n**警告内容** : 当前内存使用情况,使用率 $usage%,已使用 $used G,剩余可用 $available G, 总内存 $total G \n \"}],\"header\":{\"title\":{\"tag\":\"plain_text\",\"content\":\"[$CURR_ENV 环境]: 服务器预警\"},\"template\":\"red\"}}}"
      curl "$REQ_PATH" \
      -H "$REQ_TYPE" \
      -d "$BODY"
    fi
}  
disk(){  
    fs=$(df -h | awk '$NF=="/"{print $1}')
    for p in $fs; do  
        mounted=$(df -h |awk '$1=="'$p'"{print $NF}')  
        size=$(df -h |awk '$1=="'$p'"{print $2}')  
        used=$(df -h |awk '$1=="'$p'"{print $3}')  
        #used_percent=$(df -h |awk '$1=="'$p'"{print $5}')  
        used_percent=$(df -h | awk '$1=="'$p'"{print $5}' | tr -d '%')
        echo "${CURR_DATE} ${CURR_TIME} 硬盘 - 挂载点: $mounted , 总大小: $size , 使用: $used , 使用率: $used_percent%"  
        if [ $used_percent -ge $THRESHOLD  ]; then
           echo "disk usage >= 80"
           BODY="{\"msg_type\":\"interactive\",\"card\":{\"config\":{\"wide_screen_mode\":false,\"enable_forward\":true},\"elements\":[{\"tag\":\"markdown\",\"content\":\"\n**服务器名称** : $FOCUS_PROCESS \n**当前时间** : $CURR_DATE $CURR_TIME \n**服务器ip** : $CURR_IP \n**警告级别** :  CRITICAL \n**警告内容** : 当前磁盘使用情况,使用率 $used_percent %,已使用 $used,总大小 $size  \n \"}],\"header\":{\"title\":{\"tag\":\"plain_text\",\"content\":\"[$CURR_ENV 环境]: 服务器预警\"},\"template\":\"red\"}}}"
            curl "$REQ_PATH" \
            -H "$REQ_TYPE" \
            -d "$BODY"
        fi
    done  
  
}  
cpu  
memory  
disk

该脚本核心做了以下几件事情:

  • 监控cpu,如果cpu超过80%,则发送告警到告警群
  • 监控内存,如果内存使用率超过80%,则发送告警通知到告警群
  • 监控磁盘,如果磁盘使用率超过80%,则发送告警通知到飞书告警群

手动执行脚本,看到如下类似的告警通知:

三、配置crontab任务

1.监控脚本5s定频执行

由于 Linux 的 crontab 的定时命令格式如下:

minute hour day-of-month month-of-year day-of-week commands

意味着标准定时任务中,最小定时周期是分钟。

但是,我们的服务器负载监控,可能需要每5秒就要求执行某个shell脚本。那么就需要做一些小小的改造才能实现。

代码语言:javascript
复制
*/1 * * * * /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 5  && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 10 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 15 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 20 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 25 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 30 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 35 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 40 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 45 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 50 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log
*/1 * * * * sleep 55 && /bin/bash /opt/tools/script/load_check.sh  >>/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log

上述任务是每5s执行一次监控脚本,并且把脚本执行记录输出到带有日期格式的日志中/opt/tools/script/check_$(date +"\%Y-\%m-\%d").log。

2.脚本执行日志滚动

但是这里会带来一个隐藏的问题,这里的脚本和任务完全有我们自己控制的,并没有使用logrotate来做日志切割和滚动,可能会因为监控脚本自身的执行记录日志导致磁盘打满,那么我们需要自己清除历史日志。

在crontab中添加以下任务:

代码语言:javascript
复制
0 0 * * * /bin/find /opt/tools/script -type f -name "check_*.log" -mtime +0 -delete

每天凌晨查找/opt/tools/script目录下寻找check_*.log格式的日志,找出访问和修改时间是今天之前的文件,并且删除。

最后重启crontab使任务生效:

代码语言:javascript
复制
service crond restart

我们可以模拟创建一个历史日志check_2024-05-13.log,并且修改它的访问和修改时间:

代码语言:javascript
复制
touch -r /opt/tools/springboot-demo/pom.xml check_2024-05-13.log

这里讨了个巧,找了个今天以前的文件作为参考,修改文件的访问和修改时间为另一个文件的时间。

这样执行任务的命令:

代码语言:javascript
复制
/bin/find /opt/tools/script -type f -name "check_*.log" -mtime +0 -delete

这样就能删除check_2024-05-13.log了,也就是验证了脚本的执行日志保留一天,每天自动删除今天以前的执行日志。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-05-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PersistentCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景概述
  • 二、监控脚本
  • 三、配置crontab任务
    • 1.监控脚本5s定频执行
      • 2.脚本执行日志滚动
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档