Shell脚本配置短信报警接口:从零搭建高效监控通知系统
📑 目录导读
- 为什么选择Shell脚本实现短信报警?
- 短信报警接口的核心要素
- 主流短信服务商API对接方式
- Shell脚本编写实战:从基础到加固
- 常见问题与问答(FAQ)
- 排查与优化:让报警永不掉线
为什么选择Shell脚本实现短信报警?
在运维监控场景中,当服务器出现CPU过载、磁盘不足或服务宕机时,快速、可靠的短信通知往往是最后一道防线,相比复杂的Java/Python监控系统,Shell脚本具备以下无可替代的优势:

- 零依赖:几乎任何Linux/Unix环境都内置Bash,无需安装额外运行时
- 极轻量:一个文件即可完成HTTP请求、数据解析、重试逻辑
- 高兼容:可无缝嵌入Cron、Nagios、Zabbix、Prometheus告警钩子
- 易定制:运维人员可快速修改短信模板、分时段静默策略
注意:Shell脚本适合低并发、触发式报警,若需每秒发送数百条消息,请改用Go或Node.js。
短信报警接口的核心要素
一个可靠的短信报警接口必须包含以下能力:
| 要素 | 说明 | Shell实现方式 |
|---|---|---|
| HTTP API调用 | 通过POST/GET向短信服务商发送请求 | curl + wget |
| 鉴权机制 | API密钥、签名或Token | Authorization: Bearer $API_KEY |
| 参数组装 | 手机号、短信内容、模板ID、定时发送 | json 或 urlencode 参数拼接 |
| 结果解析 | 获取返回码、消息ID,判断发送成功与否 | jq 解析JSON / grep 纯文本 |
| 重试与降级 | 失败后自动重试,备用通道切换 | for循环 + sleep |
| 日志与审计 | 记录每次发送时间、手机号、结果 | 追加到本地日志文件 |
主流短信服务商API对接方式
1 国内主流服务商接口特点
- 阿里云短信:需签名(SignName)和模板(TemplateCode),支持国际短信
- 腾讯云短信:SmsSdkAppId + 模板ID,单次最多200个手机号
- 七牛云短信:纯HTTP API,支持语音验证码(降级方案)
- 聚合数据:通过URL拼接发送,适合快速测试
2 国际服务商(非必选但可作为备份)
- Twilio:全球短信覆盖,按区域计费,
curl请求即可 - AWS SNS:支持SMS和语音,需配置IAM权限
- Telnyx:提供独立API key,支持RESTful调用
建议:优先选择国内服务商(延迟低、成功率高),同时配置国际服务商作为故障切换。
Shell脚本编写实战:从基础到加固
1 基础版本:单通道短信发送
#!/bin/bash
# 阿里云短信配置(请替换真实值)
ACCESS_KEY="LTAI5tXXXXXXXXXXXXX"
ACCESS_SECRET="your_secret_here"
SIGN_NAME="监控报警"
TEMPLATE_CODE="SMS_123456789"
PHONE="13800138000"
ALERT_MSG="服务器CPU使用率超过80%,当前值为85%"
# 使用curl调用API(简化版,实际需计算签名)
curl -X POST "https://dysmsapi.aliyuncs.com" \
-H "Content-Type: application/json" \
-d '{
"PhoneNumbers": "'$PHONE'",
"SignName": "'$SIGN_NAME'",
"TemplateCode": "'$TEMPLATE_CODE'",
"TemplateParam": "{\"msg\":\"'"$ALERT_MSG"'\"}"
}'
2 进阶版:带重试、日志和错误处理
#!/bin/bash
# ====== 配置区 ======
API_URL="https://api.sms.example.com/send"
API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"
PHONE_LIST="13800138000,13900139000"
SENDER="监控系统"
LOG_FILE="/var/log/sms_alert.log"
MAX_RETRY=3
RETRY_DELAY=5 # 秒
# ====== 函数定义 ======
send_sms() {
local phone="$1"
local message="$2"
local retry_count=0
local response=""
while [ $retry_count -lt $MAX_RETRY ]; do
response=$(curl -s -X POST "$API_URL" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"phone\":\"$phone\",\"content\":\"$message\",\"sender\":\"$SENDER\"}")
# 解析返回结果(假定成功包含 "success":true)
if echo "$response" | grep -q '"success":true'; then
echo "$(date '+%Y-%m-%d %H:%M:%S') [SUCCESS] Phone: $phone | Msg: $message" >> "$LOG_FILE"
return 0
else
retry_count=$((retry_count + 1))
echo "$(date '+%Y-%m-%d %H:%M:%S') [RETRY-$retry_count] Phone: $phone | Response: $response" >> "$LOG_FILE"
sleep $RETRY_DELAY
fi
done
echo "$(date '+%Y-%m-%d %H:%M:%S') [FAIL] Phone: $phone | After $MAX_RETRY retries" >> "$LOG_FILE"
return 1
}
# ====== 主逻辑 ======
ALERT_CONTENT="【紧急】服务器磁盘使用率已达95%,请立即处理!"
IFS=',' read -ra PHONE_ARRAY <<< "$PHONE_LIST"
for phone in "${PHONE_ARRAY[@]}"; do
send_sms "$phone" "$ALERT_CONTENT"
done
3 高级增强:与监控系统联动
# 可被Zabbix/Nagios调用的报警脚本
# 接收参数:$1 = 手机号, $2 = 报警级别, $3 = 报警描述
ALERT_LEVEL=$2
ALERT_DESC=$3
# 根据级别降级发送频率
case $ALERT_LEVEL in
"WARNING") THROTTLE=60 ;; # 每分钟最多1条
"CRITICAL") THROTTLE=0 ;; # 不限制
*) THROTTLE=30 ;;
esac
# 限流逻辑(使用临时文件记录最后发送时间)
LAST_SENT_FILE="/tmp/sms_last_sent_$1"
if [ -f "$LAST_SENT_FILE" ] && [ $(($(date +%s) - $(cat $LAST_SENT_FILE))) -lt $THROTTLE ]; then
echo "Throttled: 距离上次发送不足$THROTTLE秒" >> "$LOG_FILE"
exit 0
fi
echo $(date +%s) > "$LAST_SENT_FILE"
# 调用发送函数...
常见问题与问答(FAQ)
Q1: 生成的签名一直不通过怎么办?
A: 签名必须与短信模板的签名名称完全一致(包含标点),阿里云控制台创建签名后需等待审核(约2-4小时),测试阶段可使用“短信测试专用签名”功能。
Q2: 批量发送手机号时,Shell脚本超时如何处理?
A: 建议分片发送,每次最多50个手机号,间隔1秒发送一批,或者使用xargs -P 5并发发送,但需注意API并发限制。
Q3: 如何在脚本中存储API密钥而不泄露?
A:
- 使用环境变量:
export SMS_API_KEY="sk-xxx" - 配置文件权限:
chmod 600 /etc/sms_config,脚本中source /etc/sms_config - 使用密钥管理工具:Hashicorp Vault、AWS Secrets Manager
Q4: 短信发送成功但手机收不到?
A:
- 检查手机是否设置骚扰拦截(尤其运营商拦截)
- 确认短信模板中的变量格式正确(如转义)
- 联系服务商客服查询
message_id的投递状态
Q5: 是否支持语音电话降级?
A: 大多数服务商支持“短信-语音”双通道,可在脚本中增加判断:
if [ $SMS_SUCCESS -eq 0 ]; then
# 触发语音呼叫
curl -X POST "https://api.voice.com/call" -d "..."
fi
排查与优化:让报警永不掉线
1 日志分析技巧
# 检查最近10次失败记录
tail -20 /var/log/sms_alert.log | grep FAIL
# 统计每日发送量
awk '{print $1}' /var/log/sms_alert.log | sort | uniq -c
2 应急降级策略
- 通道切换:同时配置2个短信服务商,当主服务返回503时切到备用
- 邮件+微信:作为最后兜底(脚本内调用
mail命令或企业微信Webhook) - 本地警报:若全部网络不可用,记录到系统日志并通过系统蜂鸣器报警
3 性能优化
- 减少curl调用次数:将多条短信打包成一次性请求(如果API支持)
- 使用HTTP持久连接:
curl --keepalive-time 60 - 异步发送:通过
&将发送放到后台,不阻塞监控主进程
通过以上步骤,你已经可以从零构建一个生产级的Shell脚本短信报警系统,核心在于:稳定的API调用 + 健壮的重试机制 + 清晰的日志审计,将该脚本与监控系统(如Cron每5分钟检测磁盘、Zabbix触发器)结合,即可实现7x24小时无人值守报警通知。