Shell脚本如何设置告警升级策略

wen 实用脚本 1

Shell脚本告警升级策略:从监控到自动化响应的完整指南

目录导读

  1. 告警升级策略的核心概念
  2. 基础Shell脚本告警实现
  3. 多级告警升级机制设计
  4. 基于时间和次数的动态升级
  5. 集成第三方通知渠道(Email/钉钉/企业微信)
  6. 实战案例:服务器宕机告警升级
  7. 常见问题与优化问答

告警升级策略的核心概念

问题1:什么是告警升级策略?
告警升级是指当某个监控事件持续未解决或恢复时,系统自动将告警级别提升,并通知更高级别负责人或采用更紧急的处理方式,在Shell脚本中实现此策略,能避免海量噪音告警,同时确保关键问题不被遗漏。

Shell脚本如何设置告警升级策略

问题2:为什么需要升级而不是简单重复告警?
假设你的Web服务器CPU持续90%以上:

  • 初级告警:发送邮件给值班运维
  • 10分钟后未恢复→升级为中级:发送短信+微信群通知
  • 30分钟后未恢复→高级升级:电话呼叫主管+创建工单

这种机制能有效过滤误报(如瞬时峰值),同时保证持续异常不会石沉大海。


基础Shell脚本告警实现

1 单次检测脚本模板

#!/bin/bash
THRESHOLD=90
LOAD=$(uptime | awk -F'load average:' '{print $2}' | cut -d, -f1 | sed 's/ //g')
if [ "$(echo "$LOAD > $THRESHOLD" | bc)" -eq 1 ]; then
    echo "WARNING: Load high - $LOAD" | mail -s "Alert" admin@example.com
fi

缺陷:此脚本每次检查都会触发邮件,无升级逻辑。


多级告警升级机制设计

1 状态文件驱动升级

通过记录连续异常次数实现线性升级:

#!/bin/bash
STATUS_FILE="/tmp/alert_status.txt"
CURRENT_COUNT=0
[ -f "$STATUS_FILE" ] && CURRENT_COUNT=$(cat $STATUS_FILE)
# 检测逻辑(假设检测失败返回1)
if [ $(check_service) -eq 1 ]; then
    NEW_COUNT=$((CURRENT_COUNT + 1))
    echo $NEW_COUNT > $STATUS_FILE
    case $NEW_COUNT in
        1) LEVEL="info"; CHANNEL="mail";;
        2) LEVEL="warning"; CHANNEL="dingtalk";;
        3) LEVEL="critical"; CHANNEL="phone";;
        *) echo "超出升级次数限制,锁定监控5分钟"; exit;;
    esac
    send_alert "$LEVEL" "$CHANNEL"
else
    # 恢复正常时重置计数器
    echo 0 > $STATUS_FILE
fi

关键设计点

  • 状态文件存储连续失败次数
  • 每级升级对应不同通知方式的函数
  • 成功时重置计数器,防止虚假升级

基于时间和次数的动态升级

1 时间窗口检测法

不仅统计次数,还引入时间变量避免长周期波动:

# 告警时间戳记录
TIMESTAMP_FILE="/tmp/alert_start_time.txt"
# 当首次触发告警时记录开始时间
if [ ! -f "$TIMESTAMP_FILE" ]; then
    date +%s > $TIMESTAMP_FILE
fi
# 计算持续时间
START_TIME=$(cat $TIMESTAMP_FILE)
NOW=$(date +%s)
DURATION=$(( (NOW - START_TIME) / 60 ))  # 单位:分钟
# 动态升级规则
if [ $DURATION -gt 30 ] && [ $CURRENT_COUNT -ge 5 ]; then
    LEVEL="critical"
elif [ $DURATION -gt 10 ]; then
    LEVEL="warning"
fi

推荐升级规则表

状态 持续时间 告警次数 升级级别
首次 <5分钟 1-2
持续 5-15分钟 3-5
顽固 >15分钟 >5

集成第三方通知渠道

1 钉钉机器人Webhook脚本

# 升级后的钉钉推送函数
send_dingtalk() {
    local msg="$1"
    local webhook_url="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
    curl -s -X POST -H "Content-Type: application/json" \
         -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"⚠️ 告警升级:$msg\"}}" \
         $webhook_url
}

2 多通道故障转移

当邮件发送失败时fallback到企业微信:

# 发送模式切换
send_alert() {
    local level=$1
    local primary_channel=$2
    local fallback_channel="wechat"
    if ! send_mail "$level" 2>/dev/null; then
        send_wechat "告警通道降级: $level (邮件不可用)"
        fallback_channel="wechat"
    fi
}

实战案例:服务器宕机告警升级

1 完整脚本框架

#!/bin/bash
# 参数配置
HOST="8.8.8.8"      # 被监控IP
TIMEOUT=5           # ping超时秒数
UPGRADE_FILE="/tmp/server_alert_upgrade.txt"
# 初始化计数器
[ ! -f "$UPGRADE_FILE" ] && echo "0|0" > $UPGRADE_FILE  # 格式:次数|时间戳
# 读取状态
IFS='|' read -r count start_time < $UPGRADE_FILE
# 检测函数
check_ping() {
    ping -c 1 -W $TIMEOUT $HOST &>/dev/null
    return $?
}
# 告警发送函数
send_wechat() {
    local msg="服务器异常告警升级: $HOST级别: $1"
    # 实际调用企业微信机器人API
}
# 主逻辑
if ! check_ping; then
    count=$((count+1))
    [ $start_time -eq 0 ] && start_time=$(date +%s)
    # 计算持续时间
    elapsed=$(( $(date +%s) - start_time ))
    # 升级策略定义
    if [ $elapsed -ge 30 ] && [ $count -ge 5 ]; then
        level="CRITICAL"
        send_wechat "紧急告警:服务器失联已超过30分钟"
    elif [ $elapsed -ge 10 ] && [ $count -ge 3 ]; then
        level="WARNING"
        send_wechat "注意:服务器中断持续建议排查" 
    else
        level="INFO"
        echo "[$(date)] 连续第 ${count} 次失联" >> /var/log/alert.log
    fi
    # 更新状态文件
    echo "${count}|${start_time}" > $UPGRADE_FILE
else
    # 恢复后重置
    echo "0|0" > $UPGRADE_FILE
    echo "[$(date)] 服务器已恢复" >> /var/log/alert.log
fi

2 执行频率设置(crontab)

*/1 * * * * /opt/scripts/ping_upgrade.sh   # 每分钟检测一次,实现1分钟粒度的升级

常见问题与优化问答

Q1:如何防止误告警导致的过度升级?
A:增加“心跳”检查机制:连续3次检测失败才视为真实异常;同时加入回调验证(如服务端口检测+进程检测双重确认)。

Q2:升级后如何自动恢复告警?
A:设计反向降级逻辑:当告警消除后,自动发送“已恢复”通知,并清空状态文件,可以使用trap命令捕捉脚本退出信号进行清理。

Q3:如何处理大量服务器的并发告警?
A:使用以下优化策略:

  • 采用flock文件锁防止并发写入状态文件
  • 为每个监控项创建独立状态文件:/tmp/alert_${host}_${service}.txt
  • 考虑使用Redis替代文件存储,提升访问效率

Q4:Shell脚本和其他工具(如Zabbix/Prometheus)的区别?
A:Shell脚本适合轻量级、短周期监控,无法替代专业监控系统的历史数据分析和图形化展示,建议专业监控负责主要告警,Shell脚本作为补充或特殊情况处理。

Q5:如何实现告警抑制(避免短时间内重复通知)?
A:在发送前计算上次通知时间差:

LAST_ALERT_TIME=$(cat /tmp/last_alert_time)
if [ $((NOW - LAST_ALERT_TIME)) -gt 120 ]; then
    # 超过2分钟才发送新告警
    echo $NOW > /tmp/last_alert_time
    send_level_upgraded_alert
fi

通过本指南,你已掌握:
✅ 基于次数的时间驱动的升级模型
✅ 多通道通知集成与故障转移
✅ 实际生产环境中的抗干扰优化技巧

建议从简单的2级升级开始(邮件→钉钉),再逐步扩展到3级并加入时间变量,别忘了定期清理状态文件避免磁盘占用(建议放入/tmp目录),最终目标是:让Shell脚本成为你7x24小时不休息的智能运维助手

抱歉,评论功能暂时关闭!