Shell脚本如何设置告警收敛规则

wen 实用脚本 1

Shell脚本告警收敛规则实战指南:从零搭建高效监控体系

📖 目录导读

  1. 告警风暴的痛点与收敛必要性
  2. Shell脚本实现告警收敛的核心机制
  3. 四大经典收敛规则实现(含代码)
  4. 常见问题解答(FAQ)
  5. 性能优化与生产部署建议

告警风暴的痛点与收敛必要性

告警风暴指单位时间内系统产生的告警数量远超处理能力,导致关键事件被淹没,例如某电商平台在促销期间,单台服务器磁盘告警每5秒触发一次,同一个问题产生4320条重复告警。
收敛的核心价值

Shell脚本如何设置告警收敛规则

  • ✅ 降低通知噪音:聚合重复事件,减少90%以上无效告警
  • ✅ 保留证据链:记录首次和最后一次发生时间,便于根因定位
  • ✅ 保护下游系统:避免监控API或IM机器人被高频请求打爆

典型场景

  • 服务端口不可达(3次重试后确认)
  • 同一IP的HTTP 500错误(10分钟内超过20次)
  • 多节点同时故障(按机房或集群聚合)

Shell脚本实现告警收敛的核心机制

1 依赖文件作为状态存储器

Shell无法像Python/Prometheus那样维护内存状态,需借助文件系统:

  • 状态文件:记录告警ID、首次时间、最新时间、聚合次数
  • 锁文件:防止并发写入导致的脏数据(关键!)

2 收敛三要素

要素 作用 Shell实现方式
聚合键 定义“相同事件”的规则 md5sumsha256sum对告警关键字取哈希
窗口期 多少秒内告警算同一事件 date +%s计算时间差
阈值 触发告警的条件 重复次数/首次间隔时间

3 安全操作原则

  • 所有文件操作需加flock独占锁
  • 使用临时文件(如${STATE_DIR}/tmp.$$)避免直接修改
  • 定期清理超过24小时的过期状态文件

四大经典收敛规则实现(含代码)

1 去重规则:相同告警不重复发送

适用:相同IP的SSH登录失败、同一服务状态码

#!/bin/bash
# 收敛规则:同时间戳唯一ID,10分钟内不重复发送
ALERT_ID=$(echo "$1" | md5sum | cut -d' ' -f1)
STATE_FILE="/tmp/alert_state/${ALERT_ID}"
LOCK_FILE="/tmp/alert_state/lock.${ALERT_ID}"
exec 200>"$LOCK_FILE"
flock -x 200
if [ -f "$STATE_FILE" ]; then
    echo "丢弃重复告警: $1"
    exit 0
fi
echo "$(date +%s)" > "$STATE_FILE"
# 发送告警逻辑...
echo "触发送告警: $1"

2 防抖规则:N次确认后再告警

适用:HTTP 5xx错误、数据库连接失败(避免网络抖动误报)

# 变量声明
ALERT_KEY="http_error_$IP"
COUNTER_FILE="/tmp/alert_counter/${ALERT_KEY}"
THRESHOLD=3
WINDOW=60  # 60秒窗口期
# 原子更新计数器
current_count=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0)
((current_count++))
if (( current_count >= THRESHOLD )); then
    # 重置计数器并发送告警
    rm -f "$COUNTER_FILE"
    send_alert "【防抖触发】${ALERT_KEY} 连续${THRESHOLD}次异常"
else
    echo "$current_count" > "$COUNTER_FILE"
    # 设置60秒后自动清除
    (sleep $WINDOW; rm -f "$COUNTER_FILE") &
fi

3 时间窗口规则:高频告警合并

适用:CPU使用率持续超阈值、磁盘空间告警

# 聚合窗口:300秒内,同一类型的告警仅发送一次摘要
WINDOW_SEC=300
ALERT_TYPE="disk_use_over_90"
SUMMARY_FILE="/tmp/alert_summary/${ALERT_TYPE}"
# 如果是窗口内第一次告警,创建状态文件并启动计时器
if [ ! -f "$SUMMARY_FILE" ]; then
    echo "1" > "$SUMMARY_FILE"
    echo "首次告警" >> "$SUMMARY_FILE"
    send_alert "初始告警: 磁盘使用率92%"
    (sleep $WINDOW_SEC; 
        # 窗口结束时,读取累计次数并发送摘要
        final_count=$(head -1 "$SUMMARY_FILE")
        send_alert "【聚合报告】磁盘告警: 共${final_count}次"
        rm -f "$SUMMARY_FILE") &
else
    # 更新计数器
    count=$(head -1 "$SUMMARY_FILE")
    ((count++))
    sed -i "1s/.*/$count/" "$SUMMARY_FILE"
    echo "追加告警: $(date)" >> "$SUMMARY_FILE"
fi

4 智能抑制规则:依赖服务不误报

适用:基础网络故障时,不发送上层应用告警

# 假设依赖链路:DNS -> Web Server -> DB
# 监控DNS服务,如果不可用,则抑制所有Web相关告警
if check_service_unavailable "DNS"; then
    echo "DNS故障,抑制全部WEB告警"
    # 创建抑制标记文件
    touch /tmp/suppress/web_alert_flag
    # 设置清理任务:每30秒检查一次DNS恢复
    while check_service_unavailable "DNS"; do
        sleep 30
    done
    rm -f /tmp/suppress/web_alert_flag
fi

常见问题解答(FAQ)

Q1:Shell脚本收敛规则对性能影响大吗?

A:单次磁盘读写约2-5ms,锁操作约0.1ms,如果每秒告警超过1000条,建议用Redis替代文件系统。最佳实践:在Shell脚本中加入快速路径——当ls /tmp/alert_state/ | wc -l超过1000时,直接跳过状态检查。

Q2:如何调试收敛规则?

A:启用日志模式

# 在脚本开头加入
export DEBUG_ALERT=true
# 在关键位置输出调试信息
if [ "$DEBUG_ALERT" = true ]; then
    echo "[DEBUG] 聚合键: $ALERT_KEY, 窗口: $WINDOW" >> /tmp/alert_debug.log
fi

Q3:收敛规则误将不同事件聚合怎么办?

A:调整聚合键的粒度,比如只对“错误代码+IP”聚合(如500_10.0.0.1),而不是单纯对URL聚合。黄金法则:聚合键颗粒度越细,误报率越低,但收敛效果也越差。

Q4:Shell脚本和Prometheus告警规则的优劣?

A

  • Shell优势:简单直接,无需额外组件,适合轻量级监控
  • Prometheus优势:内置repeat_intervalgroup_interval,支持复杂数学运算(如sum by (instance)
    建议:已有Prometheus环境用PromQL,新搭建统一监控可用Shell+Pushgateway。

性能优化与生产部署建议

1 文件系统优化

  • 使用tmpfsmount -t tmpfs -o size=50M tmpfs /tmp/alert_state
  • 设置noatime挂载选项,减少inode访问次数

2 并发控制方案

# 使用flock防止脚本并发执行
(
  flock -x 200
  # 收敛逻辑代码块
) 200>/var/lock/alert_converge.lock

3 与外部系统集成

  • 对接Prometheus:通过textfile模式写入metrics
    echo "alert_converge_total{type=\"重复\"} $(wc -l < /tmp/duplicated.log)" > /var/lib/node_exporter/textfile/alert.prom
  • 对接Slack:在收敛脚本中调用curl -d 'payload={"text":"聚合通知"}' <your-slack-webhook>
  • 对接企业微信:使用webhook机器人发送Markdown格式摘要

4 容灾与自愈

  • 状态文件损坏时自动重建:
    if ! head -1 "$STATE_FILE" 2>/dev/null | grep -qE '^[0-9]+$'; then
      rm -f "$STATE_FILE"
      mv "${STATE_FILE}.bak" "$STATE_FILE" 2>/dev/null || true
    fi
  • 脚本异常退出时清理临时文件:trap "rm -f /tmp/alert_state/*.tmp" EXIT

核心总结:Shell脚本告警收敛关键在于文件锁安全+聚合键设计+窗口期阈值,从“去重-防抖-聚合-抑制”四步走,配合tmpfsflock即可应对90%的告警收敛场景,当每秒处理告警超百级时,建议升级到Golang或Rust实现高性能版,但Shell的灵活性和低运维成本在小规模监控中仍不可替代。

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