本文目录导读:

是的,实用脚本可以批量报警,而且这恰恰是脚本自动化运维中的核心价值之一。批量报警通常指两种场景:
- 大批量触发报警(同时检测100台服务器,如果某几台宕机,自动向监控系统发送多个报警)。
- 大批量发送报警通知(将同一个告警信息,同时通过短信、邮件、钉钉/企业微信/飞书机器人发送给多个负责人)。
下面我为你提供几种最实用的脚本方案和核心代码示例,你可以根据自己的需求直接改。
批量检测并报警(最常用)
假设你需要监控100台服务器的存活状态或磁盘使用率,一旦超过阈值就报警。
核心逻辑: 脚本循环检测 -> 如果失败 -> 调用报警函数。
示例:Bash脚本(集成钉钉/企业微信机器人报警)
这个脚本可以批量检测IP列表,当机器Ping不通时,自动发送告警到群机器人。
#!/bin/bash
# 报警配置
WEBHOOK_URL="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" # 钉钉或企微机器人地址
ALARM_TITLE="【告警】服务器离线"
# 定义需要监控的IP列表(可以是文件或者直接写在数组里)
IP_LIST="
192.168.1.1
192.168.1.2
192.168.1.3
"
# 报警函数
alarm() {
local ip=$1
local message="服务器 $ip 无法Ping通,疑似宕机!时间: $(date '+%Y-%m-%d %H:%M:%S')"
# 发送到群机器人 (Markdown格式)
curl -s -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{
\"msgtype\": \"markdown\",
\"markdown\": {
\"title\": \"$ALARM_TITLE\",
\"text\": \"### $ALARM_TITLE \n \n **服务器**: $ip \n \n **状态**: 离线 \n \n **时间**: $(date '+%Y-%m-%d %H:%M:%S')\"
}
}" > /dev/null 2>&1
echo "已发送报警: $ip"
}
# 批量检测逻辑
for ip in $IP_LIST; do
# Ping检测(-c 1表示发送1个包,-W 2表示超时2秒)
ping -c 1 -W 2 $ip > /dev/null 2>&1
if [ $? -ne 0 ]; then
# 触发报警
alarm $ip
else
echo "OK: $ip"
fi
done
批量发送静态告警(如:通知所有值班人)
如果你已经有一个告警列表(来自日志、监控系统接口等),需要把这条告警同时发给N个人。
示例:Python脚本(多通道批量发送)
这个脚本可以将一条告警消息同时发送到邮件、短信、钉钉。
import smtplib
from email.mime.text import MIMEText
import requests
import json
# 配置区
DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
SMS_API_KEY = "your_sms_key"
EMAIL_SENDER = "your_email@example.com"
EMAIL_PASSWORD = "your_password"
EMAIL_RECEIVERS = ["admin1@company.com", "admin2@company.com", "admin3@company.com"]
# 模拟需要批量报警的数据
alarm_data = [
{"ip": "10.0.0.1", "type": "CPU超90%", "level": "P0"},
{"ip": "10.0.0.2", "type": "磁盘只读", "level": "P0"},
{"ip": "10.0.0.3", "type": "连接超时", "level": "P1"}
]
def send_dingtalk(msg):
"""发送钉钉机器人"""
data = {"msgtype": "text", "text": {"content": msg}}
try:
requests.post(DINGTALK_WEBHOOK, json=data, timeout=5)
except Exception as e:
print(f"钉钉报警失败: {e}")
def send_email(subject, body):
"""发送邮件"""
msg = MIMEText(body, 'plain', 'utf-8')
msg['Subject'] = subject
msg['From'] = EMAIL_SENDER
msg['To'] = ','.join(EMAIL_RECEIVERS)
try:
server = smtplib.SMTP_SSL('smtp.qq.com', 465)
server.login(EMAIL_SENDER, EMAIL_PASSWORD)
server.send_message(msg)
server.quit()
print("邮件发送成功")
except Exception as e:
print(f"邮件发送失败: {e}")
# 批量执行报警
for alarm in alarm_data:
# 格式化报警消息
alarm_msg = f"[{alarm['level']}] 服务器 {alarm['ip']} 发生告警: {alarm['type']}"
# 同时发送不同渠道
send_dingtalk(alarm_msg) # 发到群
send_email(f"严重告警: {alarm['type']}", alarm_msg) # 发到邮箱
print(f"已批量报警: {alarm_msg}")
防骚扰- 去重与聚合
如果脚本每分钟运行一次,某个机器一直宕机,它就会每分钟发一次报警,造成“报警风暴”。实用脚本需要加入去重逻辑。
核心思路:
- 状态文件记录:记录上次是否已经报警 (1=报警过, 0=正常)。
- 只有状态从
0变为1(刚出问题) 或1变为0(恢复) 时才发报警。 - 对于相同故障,在同一台机器上不重复报警(静默期)。
Bash改进版(防重复)
#!/bin/bash
ALARM_DIR="/tmp/alarm_status" # 存放状态文件
mkdir -p $ALARM_DIR
for ip in $IP_LIST; do
STATUS_FILE="${ALARM_DIR}/${ip}.status"
ping -c 1 -W 2 $ip > /dev/null 2>&1
if [ $? -ne 0 ]; then
# 如果状态文件不存在或者内容是0(正常),说明是首次出问题,才报警
if [ ! -f "$STATUS_FILE" ] || [ "$(cat $STATUS_FILE)" == "0" ]; then
alarm $ip # 调用报警函数
echo "1" > $STATUS_FILE # 标记为已报警
else
echo "已报警过,跳过重复报警: $ip"
fi
else
# 恢复正常时,如果状态是1则发恢复通知
if [ -f "$STATUS_FILE" ] && [ "$(cat $STATUS_FILE)" == "1" ]; then
echo "服务器 $ip 已恢复" # 这里也可以调用恢复报警函数
fi
echo "0" > $STATUS_FILE
fi
done
如何升级为成熟方案?
如果上面的脚本不能满足你的需求(比如需要管理1万台机器、需要权限控制、需要自定义规则),可以考虑以下路径:
- 自建告警引擎:用脚本读取
Prometheus或Zabbix的接口数据,过滤后通过脚本批量发送。 - 使用现有工具集成:
- Prometheus + Alertmanager:在
Alertmanager里配置路由,发送到所有渠道。 - 脚本 + webhook-framework:写一个脚本,把报警信息统一发送到一个中间件(如 Python Flask 服务),由中间件负责分发短信、邮件、电话。
- Prometheus + Alertmanager:在
- 编排与自动化(适合大规模批量执行):使用 Ansible 或 SaltStack 执行剧本,配合回调机制(callback plugin)实现批量报警。
实用脚本当然能批量报警,而且很简单。 按照你的实际需求,选择下面的组合即可:
| 需求 | 推荐方案 |
|---|---|
| 一次检测,多个机器出问题发多个通知 | 脚本 for 循环 + 调用报警函数 |
| 一条告警,发给多个不同的渠道 | 脚本定义 send_dingtalk, send_email, send_sms 等函数 |
| 防止重复报警 | 使用临时文件记录状态(如 /tmp/*.status) |
| 数据来自Excel/CSV/TXT | 用 awk,sed 解析,或者用 Python pandas 读取后循环报警 |
| 需要图形化/Web界面 | 脚本作为后端,配合 Flask/Django 写前端 |
如果你能告诉我:“报警来源是什么?”(如:nagios、日志文件、Zabbix)以及 “报警渠道有哪些?”(如:短信、电话、钉钉),我可以为你定制一段能直接运行的脚本。