搜索全站
报错排查 19 分钟阅读

WordPress 运维监控搭建:可用性拨测与性能告警落地方案

站点挂了自己最后一个知道,是最尴尬的事。本文给出一套可落地的监控方案:外部拨测、服务器指标采集、日志告警、WordPress 内部健康检查,附具体配置和告警阈值建议。

U
UFO_PF 2019-04-23 · 阅读 19 分钟
Wo 报错排查
阅读提示
本文约 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

建议加三个监控:

  1. 首页(HTTP 200);
  2. 一个真实文章页(确认数据库正常,不只是静态首页);
  3. /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

常见踩坑

  1. 告警太多导致麻木:阈值设太敏感,一天收 50 封邮件,最后全被过滤规则丢进垃圾箱。告警必须 actionable(需要你采取行动),否则宁可不告。
  2. 只监控首页:首页可能是纯静态或缓存命中,站点实际已挂。至少监控一个动态页面(文章页或搜索页)。
  3. 监控和被监控在同一台机器上:服务器挂了,监控也挂了,发不出告警。外部拨测必须在别的网络环境(UptimeRobot、云拨测)。
  4. 案例:某站磁盘被日志写满,数据库崩溃。但站长配的监控只告警 CPU 和内存,没有磁盘。磁盘是最容易出事的指标(日志轮转失效、备份堆积),必须有,且用 predict_linear 提前预警。
  5. 证书过期:外部拨测工具一般会监控,但自建脚本容易漏。单独加一条:

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

  1. crontab 脚本路径问题:cron 环境下 PATH 很窄,wp、mysql 等命令要用绝对路径(/usr/local/bin/wp)。
  2. 告警发不出去:脚本依赖 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"}}'

  1. 备份没监控:备份失败是最容易被忽略的事故。给备份脚本加成功/失败上报,或用 “dead man’s switch” 类服务(如 Healthchecks.io)——备份成功才 ping 一下,超时没 ping 就告警。

总结

一套够用的 WordPress 监控组合:外部拨测(UptimeRobot 或自建 Uptime Kuma)+ 云厂商主机告警 + 关键日志脚本 + WordPress 周报脚本,落地成本 1–2 小时,绝大多数服务有免费额度。配置原则:告警要 actionable(宁缺毋滥)、拨测必须在站外(否则一起挂)、磁盘和证书必监控(最容易出事且后果严重)、备份成功与否纳入监控。告警渠道优先选企业微信/钉钉/Slack 的 Webhook,实时性远好于邮件。监控搭好之后,配合WordPress 月度安全巡检清单的定期人工检查,就能从”被动救火”转向”主动运维”。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。