基于Bash脚本的自动化值班告警推送系统实战
背景
运维工作中,值班人员需要在告警发生时第一时间收到通知。传统的做法是依赖监控平台推送,但监控平台可能存在延迟或推送失败的情况。本文介绍如何基于 Bash 脚本构建一个轻量级的自动化值班告警推送系统,在监控平台告警的基础上增加一层保障,确保告警不遗漏。
系统架构
整个系统由三个核心模块组成:
- 告警采集模块:从监控平台(如 Prometheus Alertmanager)拉取告警
- 告警过滤模块:根据规则过滤重复告警、静默告警
- 告警推送模块:通过邮件、钉钉/飞书 Webhook 等渠道推送
核心脚本实现
1. 告警采集脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #!/bin/bash
ALERTMANAGER_URL="http://localhost:9093/api/v1/alerts" OUTPUT_FILE="/var/log/ops/alerts_fetched.json" LOCK_FILE="/var/lock/alert_fetch.lock"
[ -f "$LOCK_FILE" ] && exit 0 touch "$LOCK_FILE"
curl -s "$ALERTMANAGER_URL" -o "$OUTPUT_FILE"
rm -f "$LOCK_FILE"
|
2. 告警过滤与处理脚本
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
| #!/bin/bash
ALERT_FILE="/var/log/ops/alerts_fetched.json" PROCESSED_FILE="/var/log/ops/alerts_processed.json" DEDUP_FILE="/var/log/ops/alerts_dedup.json"
process_alerts() { jq '[.[] | select(.startsAt) | select(.status != "resolved")]' "$ALERT_FILE" \ > "$PROCESSED_FILE" }
deduplicate_alerts() { jq -s 'unique_by(.labels.alertname + .labels.instance)' \ "$PROCESSED_FILE" > "$DEDUP_FILE" }
format_alert_text() { local alert=$1 local alertname=$(echo "$alert" | jq -r '.labels.alertname') local instance=$(echo "$alert" | jq -r '.labels.instance') local severity=$(echo "$alert" | jq -r '.labels.severity') local description=$(echo "$alert" | jq -r '.annotations.description') echo "【${severity^^}】${alertname}" echo "实例:${instance}" echo "描述:${description}" echo "时间:$(date '+%Y-%m-%d %H:%M:%S')" }
process_alerts deduplicate_alerts
|
3. 告警推送脚本
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 39
| #!/bin/bash
DEDUP_FILE="/var/log/ops/alerts_processed.json" WEBHOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/xxx" EMAIL_TO="oncall@example.com"
send_to_feishu() { local message=$1 local payload=$(cat <<EOF { "msg_type": "text", "content": { "text": "${message}" } } EOF ) curl -X POST -H "Content-Type: application/json" \ -d "$payload" "$WEBHOOK_URL" 2>/dev/null }
send_to_email() { local subject=$1 local body=$2 echo "$body" | mail -s "$subject" "$EMAIL_TO" }
while IFS= read -r alert; do alertname=$(echo "$alert" | jq -r '.labels.alertname') instance=$(echo "$alert" | jq -r '.labels.instance') severity=$(echo "$alert" | jq -r '.labels.severity') message="【${severity^^}】${alertname} 告警发生在 ${instance}" send_to_feishu "$message" send_to_email "[${severity^^}] ${alertname} 告警通知" "$message" done < <(jq -c '.[]' "$DEDUP_FILE")
|
Cron 调度配置
将脚本加入 Cron 调度,每分钟执行一次:
1 2 3 4 5 6 7
| crontab -e
* * * * * /opt/ops/scripts/alert_fetch.sh * * * * * sleep 10 && /opt/ops/scripts/alert_process.sh * * * * * sleep 20 && /opt/ops/scripts/alert_notify.sh
|
告警收敛策略
为避免告警风暴,引入告警收敛机制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #!/bin/bash
ALERT_FILE="/var/log/ops/alerts_processed.json" MERGED_FILE="/var/log/ops/alerts_merged.json"
merge_alerts() { jq --argjson interval 300 ' map({ key: .labels.alertname, value: . }) | from_entries | to_entries | map(.value | .createdAt = (.startsAt | fromdateiso8601) | select((now | floor) - .createdAt < $interval)) ) ' "$ALERT_FILE" > "$MERGED_FILE" }
merge_alerts
|
脚本日志与监控
为确保脚本稳定运行,需要完善的日志记录:
1 2 3 4 5 6 7 8 9
| LOG_FILE="/var/log/ops/alert_system.log"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" }
log "INFO: Alert fetch started"
log "INFO: Alert fetch completed, processed $(wc -l < "$OUTPUT_FILE") alerts"
|
同时建议通过 Prometheus 监控 Cron 任务的执行状态:
1 2 3 4 5
| - job_name: 'cron_alerts' scrape_interval: 30s static_configs: - targets: ['localhost:9000']
|
总结
通过 Bash 脚本构建的自动化值班告警推送系统具有以下优势:
| 特性 |
说明 |
| 轻量级 |
无需额外依赖,纯 Shell 实现 |
| 可扩展 |
易于添加新的告警渠道 |
| 可靠 |
去重 + 收敛机制避免告警风暴 |
| 可观测 |
完善的日志记录,便于排查问题 |
该方案适用于中小规模运维场景,大规模场景建议结合专业的监控平台使用。