Shell脚本如何配置短信报警接口

wen 实用脚本 1

Shell脚本配置短信报警接口:从零搭建高效监控通知系统

📑 目录导读

  1. 为什么选择Shell脚本实现短信报警?
  2. 短信报警接口的核心要素
  3. 主流短信服务商API对接方式
  4. Shell脚本编写实战:从基础到加固
  5. 常见问题与问答(FAQ)
  6. 排查与优化:让报警永不掉线

为什么选择Shell脚本实现短信报警?

在运维监控场景中,当服务器出现CPU过载、磁盘不足或服务宕机时,快速、可靠的短信通知往往是最后一道防线,相比复杂的Java/Python监控系统,Shell脚本具备以下无可替代的优势:

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、定时发送 jsonurlencode 参数拼接
结果解析 获取返回码、消息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:

  1. 使用环境变量:export SMS_API_KEY="sk-xxx"
  2. 配置文件权限:chmod 600 /etc/sms_config,脚本中source /etc/sms_config
  3. 使用密钥管理工具: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小时无人值守报警通知。

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