本文约 7,242 字,预计阅读 19 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:用户告诉你网站挂了
最尴尬的运维场景:
- 客户发消息”你们网站打不开了”,你才发现已经挂了 3 小时;
- 百度快照更新停滞,其实是站点 500 了一周,爬虫抓不到;
- SSL 证书过期,浏览器拦截,你两天后才知道;
- 磁盘满了,数据库写不进去,备份也失败了。
没有监控 = 靠运气运维。 一套基础监控的成本几乎为零(很多服务有免费额度),搭建时间也就一两个小时,但能把这些事故从”用户发现”变成”你先发现”。
原理分析:监控的四个层次
| 层次 | 监控什么 | 代表工具 | 能发现什么 |
|---|---|---|---|
| 外部拨测 | HTTP 状态码、响应时间、证书有效期 | UptimeRobot、阿里云拨测、Cloudflare | 站点整体不可用、证书过期、DNS 故障 |
| 主机指标 | CPU、内存、磁盘、网络、进程 | Prometheus + Node Exporter、云监控 | 资源耗尽、磁盘满、OOM |
| 服务日志 | Nginx 5xx、PHP Fatal、MySQL 慢查询 | 日志服务、grep + 定时脚本 | 具体错误、攻击、性能退化 |
| 应用内部 | WP-Cron、站点健康、更新状态 | WP 插件、自定义脚本 | 计划任务失效、插件漏洞 |
四个层次都要有,因为它们能发现的问题不重叠:
- 外部拨测能发现”进程还在但返回 500″——主机监控发现不了;
- 主机监控能发现”磁盘快满了”——拨测发现不了(还没挂);
- 日志能告诉你”为什么”,拨测只告诉你”挂了”。
告警渠道:邮件(最低要求)+ 短信/电话(严重告警)+ Webhook 到企业微信/钉钉/飞书/Slack(推荐,实时性最好)。
保姆级实操
第一层:外部拨测(10 分钟搞定,优先级最高)
方案 A:UptimeRobot(免费,够用)
- 免费版:50 个监控项,5 分钟间隔;
- 支持 HTTP(s)、关键词监控、端口、Ping;
- 告警渠道:邮件、Webhook、Slack、Telegram。
配置:
Monitor Type: HTTP(s)
URL: https://mimangfei.com/
Interval: 5 分钟
Alert Contacts: 你的邮箱 / Webhook
建议加三个监控:
- 首页(HTTP 200);
- 一个真实文章页(确认数据库正常,不只是静态首页);
/wp-login.php(确认 PHP 和后台可用)。
关键词监控(高级用法):监控首页是否包含某个只有动态渲染才有的字符串,如果返回的是 CDN 缓存的静态页或维护页,能被发现。
方案 B:云厂商拨测(国内更准)
- 阿里云「云监控 – 站点监控」:支持国内多地域拨测;
- 腾讯云「云拨测」;
- 优点:能从多个运营商线路探测,国内访问问题更准。
方案 C:自建(有服务器的话)
轻量方案,Uptime Kuma(Docker 部署,界面漂亮,免费):
docker run -d --restart=always \
-p 3001:3001 \
-v uptime-kuma:/app/data \
--name uptime-kuma \
louislam/uptime-kuma:1
配置 90+ 种通知渠道(含企业微信、钉钉、飞书、Bark、Telegram)。
告警阈值建议:
- 连续 2 次探测失败才告警(避免网络抖动误报);
- 响应时间超过 3 秒告警(性能退化预警);
- 证书剩余 7 天告警(提前续期)。
第二层:主机指标监控
方案 A:云厂商自带(最省事)
阿里云/腾讯云的云监控默认提供 CPU、内存、磁盘、网络的基础指标,只需在控制台配置告警规则:
CPU 使用率 > 80% 持续 5 分钟 → 告警
内存使用率 > 85% 持续 5 分钟 → 告警
磁盘使用率 > 85% → 告警
需要安装云监控 Agent(阿里云默认已装)。
方案 B:Prometheus + Grafana(自建,功能强)
# Node Exporter(采集主机指标)
docker run -d --name node-exporter --restart=always \
-p 9100:9100 \
-v /:/host:ro,rslave \
--pid host \
quay.io/prometheus/node-exporter:latest \
--path.rootfs=/host
prometheus.yml:
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
- job_name: 'nginx'
static_configs:
- targets: ['localhost:9113'] # nginx-exporter
关键告警规则:
groups:
- name: host
rules:
- alert: HighCPU
expr: 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m
labels: { severity: warning }
annotations:
summary: "CPU 使用率过高"
- alert: DiskWillFillIn4Hours
expr: predict_linear(node_filesystem_free_bytes[1h], 4*3600) < 0
for: 5m
labels: { severity: critical }
annotations:
summary: "磁盘将在 4 小时内写满"
- alert: HighMemory
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
for: 5m
labels: { severity: critical }
predict_linear 那条特别有用——磁盘”快满了”比”已经满了”有价值得多。
方案 C:极简脚本(不想装任何东西)
#!/bin/bash
# /usr/local/bin/check-server.sh
THRESHOLD=85
ALERT_EMAIL="admin@mimangfei.com"
HOST=$(hostname)
# 磁盘
DISK=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
[ "$DISK" -gt "$THRESHOLD" ] && \
echo "磁盘使用率 ${DISK}%" | mail -s "[告警] ${HOST} 磁盘空间不足" "$ALERT_EMAIL"
# 内存
MEM=$(free | awk '/Mem:/ {printf "%.0f", $3/$2*100}')
[ "$MEM" -gt "$THRESHOLD" ] && \
echo "内存使用率 ${MEM}%" | mail -s "[告警] ${HOST} 内存不足" "$ALERT_EMAIL"
# 关键进程
for svc in nginx php8.2-fpm mysql redis-server; do
systemctl is-active --quiet "$svc" || \
echo "$svc 已停止" | mail -s "[严重] ${HOST} ${svc} 服务停止" "$ALERT_EMAIL"
done
# 站点可用性
CODE=$(curl -s -o /dev/null -w "%{http_code}" -m 10 https://mimangfei.com/)
[ "$CODE" != "200" ] && \
echo "站点返回 $CODE" | mail -s "[严重] mimangfei.com 访问异常" "$ALERT_EMAIL"
chmod +x /usr/local/bin/check-server.sh
# 每 5 分钟执行一次
echo "*/5 * * * * /usr/local/bin/check-server.sh" | crontab -
第三层:日志告警
Nginx 5xx 告警
#!/bin/bash
# 统计最近 5 分钟的 5xx 数量
COUNT=$(awk -v d="$(date -d '5 min ago' '+%d/%b/%Y:%H:%M')" \
'$4 ~ "[" { if ($4 >= "["d) print }' /var/log/nginx/access.log | \
awk '$9 ~ /^5[0-9][0-9]$/' | wc -l)
if [ "$COUNT" -gt 10 ]; then
tail -50 /var/log/nginx/error.log | \
mail -s "[告警] 5 分钟内出现 ${COUNT} 次 5xx" admin@mimangfei.com
fi
PHP 致命错误告警
# php.ini 里确保开启错误日志
# log_errors = On
# error_log = /var/log/php8.2-fpm-error.log
grep -c "PHP Fatal error" /var/log/php8.2-fpm-error.log
Fail2ban 的邮件告警:见用 Fail2ban 防护 WordPress 暴力破解,配置 action_mwl 即可收到封禁通知,这本身就是一种入侵告警。
集中式日志(站点多时):
- 阿里云 SLS、腾讯云 CLS:按量付费,小站几块钱一个月;
- 自建 ELK / Loki:有运维成本。
第四层:WordPress 内部健康检查
每周自动巡检并邮件报告(结合WordPress 月度安全巡检清单):
# /usr/local/bin/wp-weekly-report.sh
#!/bin/bash
SITE=/var/www/mimangfei
{
echo "WordPress 周报 $(date +%F)"
echo
echo "== 核心校验 =="
wp --path=$SITE core verify-checksums --allow-root 2>&1
echo
echo "== 待更新 =="
wp --path=$SITE core check-update --allow-root 2>&1
wp --path=$SITE plugin list --update_available=available --allow-root
echo
echo "== 数据库大小 =="
wp --path=$SITE db size --allow-root
echo
echo "== 磁盘 =="
df -h / | tail -1
echo
echo "== 计划任务状态 =="
wp --path=$SITE cron event list --due-now --allow-root | head -10
} | mail -s "WordPress 周报 - mimangfei.com" admin@mimangfei.com
0 9 * * 1 /usr/local/bin/wp-weekly-report.sh
WP-Cron 失效告警:
# 检查是否有逾期未执行的任务
DUE=$(wp --path=$SITE cron event list --due-now --format=count --allow-root 2>/dev/null)
[ "$DUE" -gt 20 ] && echo "有 $DUE 个逾期任务" | mail -s "[告警] WP-Cron 异常" admin@mimangfei.com
插件漏洞监控:
- Wordfence / iThemes Security 自带漏洞邮件通知;
- 订阅 WordPress 安全公告;
- 用
wp plugin list+ WPScan 定期扫描:
bash
wpscan --url https://mimangfei.com --enumerate vp --api-token 你的token
常见踩坑
- 告警太多导致麻木:阈值设太敏感,一天收 50 封邮件,最后全被过滤规则丢进垃圾箱。告警必须 actionable(需要你采取行动),否则宁可不告。
- 只监控首页:首页可能是纯静态或缓存命中,站点实际已挂。至少监控一个动态页面(文章页或搜索页)。
- 监控和被监控在同一台机器上:服务器挂了,监控也挂了,发不出告警。外部拨测必须在别的网络环境(UptimeRobot、云拨测)。
- 案例:某站磁盘被日志写满,数据库崩溃。但站长配的监控只告警 CPU 和内存,没有磁盘。磁盘是最容易出事的指标(日志轮转失效、备份堆积),必须有,且用
predict_linear提前预警。 - 证书过期:外部拨测工具一般会监控,但自建脚本容易漏。单独加一条:
bash
echo | openssl s_client -connect mimangfei.com:443 -servername mimangfei.com 2>/dev/null \
| openssl x509 -noout -checkend 604800 || echo "证书 7 天内过期" | mail -s "[告警] SSL 证书即将过期" admin@mimangfei.com
- crontab 脚本路径问题:cron 环境下
PATH很窄,wp、mysql等命令要用绝对路径(/usr/local/bin/wp)。 - 告警发不出去:脚本依赖
mail命令,但服务器没配 MTA。参考WordPress SMTP 邮件配置配好发信能力,或改用 Webhook(curl 请求企业微信机器人)更可靠:
bash
curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx" \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"[告警] mimangfei.com 站点返回 502"}}'
- 备份没监控:备份失败是最容易被忽略的事故。给备份脚本加成功/失败上报,或用 “dead man’s switch” 类服务(如 Healthchecks.io)——备份成功才 ping 一下,超时没 ping 就告警。
总结
一套够用的 WordPress 监控组合:外部拨测(UptimeRobot 或自建 Uptime Kuma)+ 云厂商主机告警 + 关键日志脚本 + WordPress 周报脚本,落地成本 1–2 小时,绝大多数服务有免费额度。配置原则:告警要 actionable(宁缺毋滥)、拨测必须在站外(否则一起挂)、磁盘和证书必监控(最容易出事且后果严重)、备份成功与否纳入监控。告警渠道优先选企业微信/钉钉/Slack 的 Webhook,实时性远好于邮件。监控搭好之后,配合WordPress 月度安全巡检清单的定期人工检查,就能从”被动救火”转向”主动运维”。
