curl 与 shell 轻量接口巡检

举报
yd_281239125 发表于 2026/11/06 09:11:00 2026/11/06
【摘要】 Prometheus 加 blackbox_exporter、云监控的可用性探测,都比手写脚本完善。但很多团队的真实需求只是“十几个接口、每五分钟看一次、挂了在群里说一声”。为这点事搭一套采集、存储和

一、先明确要解决的问题

Prometheus 加 blackbox_exporter、云监控的可用性探测,都比手写脚本完善。但很多团队的真实需求只是“十几个接口、每五分钟看一次、挂了在群里说一声”。为这点事搭一套采集、存储和面板,成本远高于收益。

自研脚本真正要解决的有三件事:能不能反复执行而结果一致(幂等)、失败信息能不能留档对比、告警能不能不刷屏。这三件事和“能不能探通”无关,却决定了这套东西能不能长期跑下去。

二、先手动验证一个接口

别急着写循环,先用一条命令确认输出格式符合预期:

curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' \
  --max-time 5 --retry 2 --retry-delay 1 \
  https://www.huaweicloud.com/

几个容易踩的点:

  • -sS:静默进度条但保留错误信息,出错时能看到原因。
  • -o /dev/null:丢掉 body,巡检只看状态码和耗时。
  • --max-time 必须给,否则 DNS 解析或 TLS 握手卡住时,整个脚本会被一个接口拖死。
  • 接口返回 404/500 时,curl 的退出码仍是 0。判断成败只能看 %{http_code};只有连不上、超时这类情况退出码才非 0,此时要兜底成 000。

三、把循环写成幂等的

幂等在这里的具体含义是:跑一次和跑十次,系统状态和输出完全一样。对应三条约束:

  1. 不要用 set -e。第一个接口超时就退出,后面的接口根本没被巡检,这次结果不可重复。用 set -uo pipefail 即可。
  2. 结果文件覆盖写,不追加。每次产出同一份 last.tsv,随时可以 diff 出变化。
  3. 告警只和上一次状态比,状态翻转才发。这样连续失败不会每五分钟刷一遍群。

脚本对被测系统只读,唯一的副作用是本地状态文件,且用 mv 原子替换,中途被打断也不会留下半份状态。

#!/usr/bin/env bash
set -uo pipefail

TARGETS=(
  "home|https://www.huaweicloud.com/|200"
  "api|https://bss.myhuaweicloud.com/v1/health|200"
)
STATE=/var/lib/probe/state.tsv
OUT=/var/log/probe/last.tsv
mkdir -p "$(dirname "$STATE")" "$(dirname "$OUT")"
touch "$STATE"

tmp=$(mktemp)
for t in "${TARGETS[@]}"; do
  IFS='|' read -r name url want <<<"$t"
  out=$(curl -sS -o /dev/null -w '%{http_code} %{time_total}' \
        --max-time 5 --retry 2 --retry-delay 1 "$url" 2>/dev/null) || out="000 0"
  read -r code cost <<<"$out"
  ok=FAIL; [ "$code" = "$want" ] && ok=OK
  printf '%s\t%s\t%s\t%s\n' "$name" "$ok" "$code" "$cost" >>"$tmp"
done

# 只在状态翻转时输出一行,其余静默
while IFS=$'\t' read -r name ok code cost; do
  prev=$(awk -F'\t' -v n="$name" '$1==n{print $2}' "$STATE")
  [ -n "$prev" ] && [ "$ok" != "$prev" ] && \
    echo "[$(date -Is)] $name $prev -> $ok (http=$code t=${cost}s)"
done <"$tmp"

mv "$tmp" "$OUT"
awk -F'\t' '{print $1"\t"$2}' "$OUT" >"$STATE"

四、挂到 crontab 并验证幂等

*/5 * * * * /usr/local/bin/probe.sh >> /var/log/probe/alerts.log 2>&1

验证方法很直接:

  • 连续执行两次,diff 两份 last.tsv 应当无输出。
  • 用 iptables -A OUTPUT -d <ip> -j DROP 模拟故障,日志里应只出现一次 OK -> FAIL,之后不再刷。
  • 恢复规则后,应只再出现一次 FAIL -> OK。

另外注意最坏耗时约为 (retry+1) × max-time,cron 周期要留够,否则进程会堆积。接口多时可以用 curl 7.66+ 的 --parallel 并发拉取。

五、小结

这套巡检的价值不在“能发请求”,而在“每次跑完都是同一份可对比的结果”。三条线守住了幂等:出错不中断、输出覆盖写、告警看翻转。代码只有几十行,随时可以改目标、改阈值,也能在出问题时用 bash -x 单步复现,这是重型监控方案换不来的可控性。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。