私有部署服务挂了没人管?最低成本告警与自愈实践
服务挂了几个小时才发现,是很多个人/小团队私有部署的常态。
尤其是学生项目、个人工具、内部系统,往往没有专人 7×24 盯着。挂了就挂了,直到用户(或者自己)来用才发现。
我给自己的私有服务做了一套最低成本的告警 + 自愈方案,核心原则就三条:
- 推送通道稳定可用(微信推送、飞书/钉钉、自建工具)
- 成本尽可能低(免费额度 + 现成组件,不堆 Prometheus/Grafana)
- 能自愈就先自愈,告警只是兜底
整套东西跑下来,每月几乎零额外费用,维护成本也很低。
整体思路

简单来说分三层:
- 健康检查:本地脚本 / systemd / Uptime Kuma
- 自愈:失败就重启(带冷却,防止抖动)
- 告警:微信(Server酱 / PushPlus)+ 飞书/钉钉机器人 + 邮件兜底
监控和被监控尽量不要完全跑在同一台机器上(否则整机挂了就一起静音)。如果只有一台机器,至少把「外部可达性检查」放在别处,或者用更轻量的本地方案。
1. 最简本地自愈:systemd + 健康检查脚本
很多服务本身用 systemd 管理就够了。
# /etc/systemd/system/my-app.service
[Unit]
Description=My Private App
After=network.target
[Service]
Type=simple
User=app
WorkingDirectory=/opt/my-app
ExecStart=/opt/my-app/bin/start.sh
Restart=on-failure
RestartSec=10
StartLimitIntervalSec=60
StartLimitBurst=5
# 可选:资源限制,防止失控
# MemoryMax=512M
# CPUQuota=50%
[Install]
WantedBy=multi-user.target
Restart=on-failure + RestartSec 已经能解决大部分「进程直接挂掉」的情况。
如果服务是「假活」(进程在,但接口已经 5xx 或卡死),就需要主动健康检查。
写一个简单的检查脚本:
#!/bin/bash
# /opt/scripts/healthcheck-my-app.sh
URL="http://127.0.0.1:8080/health"
TIMEOUT=5
MAX_FAIL=3
STATE_FILE="/tmp/my-app-health.failcount"
fail_count=$(cat "$STATE_FILE" 2>/dev/null || echo 0)
if curl -sf --max-time $TIMEOUT "$URL" > /dev/null; then
echo 0 > "$STATE_FILE"
exit 0
fi
fail_count=$((fail_count + 1))
echo $fail_count > "$STATE_FILE"
if [ "$fail_count" -ge "$MAX_FAIL" ]; then
echo "$(date) healthcheck failed $fail_count times, restarting..."
systemctl restart my-app.service
echo 0 > "$STATE_FILE"
# 这里可以顺便发一次告警
/opt/scripts/notify.sh "my-app 健康检查连续失败,已自动重启"
fi
用 systemd timer 定期跑:
# /etc/systemd/system/my-app-health.timer
[Unit]
Description=My App Health Check
[Timer]
OnBootSec=1min
OnUnitActiveSec=1min
AccuracySec=10s
[Install]
WantedBy=timers.target
对应的 service 只负责执行脚本即可。
防抖很重要:连续失败 N 次才重启,并清零计数,避免短暂网络抖动导致反复重启。
2. Docker 场景
Docker 自带重启策略已经很好用:
services:
my-app:
image: my-app:latest
restart: unless-stopped # 或 always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
配合 restart: unless-stopped,健康检查失败后 Docker 会自动重启容器。
如果想更主动一点,可以再加一个 sidecar 或外部脚本去 docker restart。
3. 告警通道
微信推送(推荐)
目前最省事的两个:
- Server酱(https://sct.ftqq.com):注册免费,每天有免费额度,一行 curl 就能推。
- PushPlus(https://www.pushplus.plus):支持微信模板消息,免费额度也够个人用。
示例(Server酱):
#!/bin/bash
# /opt/scripts/notify.sh
TITLE="$1"
CONTENT="${2:-}"
SENDKEY="你的SCT_KEY"
curl -s -X POST "https://sctapi.ftqq.com/${SENDKEY}.send" \
-d "title=${TITLE}" \
-d "desp=${CONTENT}"
飞书 / 钉钉机器人
免费、稳定、支持 Markdown,适合团队或自己多端接收。
飞书自定义机器人 webhook 直接 POST JSON 即可。
邮件兜底
用 163 / QQ 邮箱 + 授权码,走 SMTP,几乎永远能通。当作最后兜底。
4. 想更省心:上 Uptime Kuma
如果服务不止一两个,或者希望有漂亮的状态页和历史记录,直接上 Uptime Kuma。
它是目前个人/小团队最推荐的自托管监控工具之一:
- Docker 一行部署
- 支持 HTTP、TCP、Ping、DNS、Docker 容器、关键字、证书过期等
- 通知渠道非常多(包括 webhook,可对接 Server酱、飞书、钉钉)
- 资源占用极低

docker run -d \
--restart=always \
-p 3001:3001 \
-v uptime-kuma:/app/data \
--name uptime-kuma \
louislam/uptime-kuma:1
关键建议:尽量不要和被监控的核心服务跑在同一台机器上。如果只有一台机器,至少把「公网可达性检查」放到另一台便宜的机器(或者朋友的机器)上。
Uptime Kuma 本身也支持通知到 Server酱 / 飞书等,配置一次就行。
5. 实际使用中的几个注意点
冷却与防抖
不要「一失败就立刻重启 + 立刻告警」。连续失败、时间窗口、重启冷却都要有,否则半夜会被刷屏,或者服务陷入重启循环。告警分级
- 自动重启成功 → 发一条 info
- 重启多次仍失败 → 发 critical
- 磁盘/内存打满 → 单独告警
日志别丢
自愈之后,最好把最近的日志截一段一起推过来,方便事后排查。不要过度设计
个人项目真的不需要完整 Prometheus + Grafana + Alertmanager 那一套。能用脚本 + 几个 webhook 解决的,就别上重型方案。备份与配置也要管
告警和自愈脚本本身也要纳入版本管理,或者至少定期备份。机器重装后能快速恢复。
成本与效果
我目前这套方案:
- 额外费用:基本为 0(免费推送额度足够)
- 维护时间:最初配置大概半天,之后几乎不用管
- 效果:大部分「进程挂了 / 接口假死」的情况能在 1–2 分钟内自愈,并收到通知
当然它解决不了「整机断电、机房网络全挂、磁盘物理损坏」这种问题,那需要更高层级的容灾。但对个人私有部署来说,已经足够把「挂了几个小时才发现」变成「挂了马上知道,并且大概率自己起来了」。
总结
最低成本并不等于简陋。
用好 systemd 的重启策略、加一层轻量健康检查、对接稳定可用的推送通道,再视需要上一个 Uptime Kuma,就已经能覆盖绝大多数个人/小团队场景。
真正重要的不是工具有多花哨,而是:
服务挂了,你能不能在用户发现之前知道,并且尽量让它自己先起来。
如果你也有类似需求,可以从「给最核心的一个服务加 systemd Restart + 一个简单的健康检查脚本」开始,先跑起来再说。
有问题欢迎在评论区交流。
私有部署服务挂了没人管?最低成本告警与自愈实践
https://wangling.hauchet.cn/archives/private-service-low-cost-alert-self-heal
评论