VPS 管理员最常见的错误之一,就是在服务器出现问题造成损失之后才发现异常。CPU 跑满 100% 导致应用响应迟缓、内存耗尽引发进程被强制终止、磁盘写满使数据库无法写入——这些问题只要配置了正确的监控警报,都是完全可以预防的。主动预防故障与被动响应宕机的关键区别,在于是否拥有一套能在问题失控之前提前通知您的警报系统。

本指南将带您从零开始在 Linux VPS 上搭建完整的警报系统:选择合适的工具、配置阈值、通过 Telegram 和邮件发送通知,并验证整个流程是否正常运行。示例涵盖 CPU、内存、磁盘和服务可用性,适用于运行 WordPress、Node.js、Docker 或企业应用的任何 VPS。

监控与警报:为何两者缺一不可

许多 VPS 管理员搭建了漂亮的 Grafana 实时仪表盘,显示 CPU 和内存图表,但凌晨 3 点出现问题时没有人盯着屏幕,仪表盘便毫无用处。一套好的警报系统相当于您全天候驻守服务器的"眼睛"。

举个实际例子:晚上 8 点磁盘使用率达到 90%。没有警报,您可能要到第二天早上才发现。有了警报,手机立刻收到 Telegram 消息。您 SSH 登入服务器,清理旧日志文件,磁盘使用率降回 60%,数据库从未中断写入。零停机,零数据丢失。

为 VPS 选择合适的警报工具

Linux VPS 监控与警报有多种成熟方案可选,最佳选择取决于您管理的服务器数量以及所需的灵活程度。

工具 复杂度 适用场景 通知方式
Netdata 简单 单台 VPS、快速上手 Email、Telegram、Slack、PagerDuty
Prometheus + Alertmanager 中–高 多台服务器、自定义应用指标 Email、Telegram、Webhook、PagerDuty
Zabbix 高 企业级、大型基础设施 Email、短信、Webhook
Shell 脚本 + Cron 简单(自制) 无需额外软件的定向警报 Email、Telegram、Line Notify

对于典型的 Ubuntu/Debian VPS,建议从 Netdata 入手——一条命令即可安装集监控、警报和内置仪表盘于一体的完整套件。当您需要完全掌控或管理多台服务器时,再迁移到 Prometheus。

安装 Netdata 并配置 Telegram 警报

Netdata 是从零开始搭建可用警报系统的最快路径。它默认采集超过一千个指标,提供实时仪表盘,并且无需任何外部数据库或额外组件即可触发警报。

安装 Netdata

wget -O /tmp/netdata-kickstart.sh https://my-netdata.io/kickstart.sh
sudo bash /tmp/netdata-kickstart.sh --stable-channel --disable-telemetry

安装完成后,Netdata 运行于 http://your-vps-ip:19999。请配置防火墙规则限制访问,避免公开暴露。

配置 Telegram 通知

编辑 /etc/netdata/health_alarm_notify.conf:

SEND_TELEGRAM="YES"
TELEGRAM_BOT_TOKEN="YOUR_BOT_TOKEN_HERE"
TELEGRAM_CHAT_ID="YOUR_CHAT_ID_HERE"
DEFAULT_RECIPIENT_TELEGRAM="YOUR_CHAT_ID_HERE"

自定义 CPU 警报阈值

警报规则存放在 /etc/netdata/health.d/ 中。创建自定义 CPU 规则:

# /etc/netdata/health.d/cpu-custom.conf
alarm: cpu_usage_warning
  on: system.cpu
  lookup: average -15m unaligned of user,system,softirq,irq,guest
  units: %
  every: 1m
  warn: $this > 80
  crit: $this > 90
  delay: down 15m multiplier 1.5 max 1h
  info: CPU usage exceeds defined threshold
  to: sysadmin

无需重启即可重新加载:

sudo kill -USR2 $(pidof netdata)

使用 Prometheus + Alertmanager 实现高级警报

如果您需要对警报路由、抑制、静默和分组进行精细控制,或者需要管理多台服务器,Prometheus 与 Alertmanager 是行业标准方案。配置步骤较多,但灵活性大幅提升。

安装 Node Exporter 采集系统指标

wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar xf node_exporter-1.7.0.linux-amd64.tar.gz
sudo mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/

sudo tee /etc/systemd/system/node_exporter.service <<'EOF'
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo useradd -rs /bin/false node_exporter
sudo systemctl enable --now node_exporter

内存与磁盘警报规则

# /etc/prometheus/rules/server_alerts.yml
groups:
  - name: server_alerts
    rules:
      - alert: HighMemoryUsage
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High memory on {{ $labels.instance }}"
          description: "Memory used: {{ printf \"%.1f\" $value }}%"

      - alert: DiskSpaceLow
        expr: (1 - (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"})) * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Low disk space on {{ $labels.instance }}"
          description: "{{ $labels.mountpoint }} is {{ printf \"%.1f\" $value }}% full"

      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Instance {{ $labels.instance }} is down"
          description: "{{ $labels.instance }} has been unreachable for 1 minute"

配置 Alertmanager 通过 Telegram 发送通知

在 Prometheus 中定义好警报规则后,配置 Alertmanager 将通知路由到 Telegram:

# /etc/alertmanager/alertmanager.yml
global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'instance']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 3h
  receiver: 'telegram-notifications'

receivers:
  - name: 'telegram-notifications'
    telegram_configs:
      - bot_token: 'YOUR_BOT_TOKEN'
        chat_id: YOUR_CHAT_ID
        parse_mode: 'HTML'
        message: |
          <b>{{ .Status | toUpper }}</b> - {{ .GroupLabels.alertname }}
          {{ range .Alerts }}
          <b>Instance:</b> {{ .Labels.instance }}
          <b>Details:</b> {{ .Annotations.description }}
          {{ end }}

inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'instance']

inhibit_rules 部分用于在同一实例已触发严重警报时,抑制重复的警告级别通知——这是减少生产环境警报疲劳的关键功能。

使用 Shell 脚本与 Cron 实现最简警报

如果您不想安装任何额外软件,一个简单的 Shell 脚本结合 Cron 即可针对最关键的阈值提供有效警报。这种方式完全自给自足,易于理解。

#!/bin/bash
# /opt/monitor/check_resources.sh

TELEGRAM_TOKEN="YOUR_BOT_TOKEN"
CHAT_ID="YOUR_CHAT_ID"
HOSTNAME=$(hostname)

send_alert() {
  curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
    -d chat_id="${CHAT_ID}" \
    -d parse_mode="HTML" \
    -d text="$1" >/dev/null
}

# CPU check (5-minute load average vs core count)
CPU_LOAD=$(awk '{print $1}' /proc/loadavg)
CPU_CORES=$(nproc)
CPU_PERCENT=$(echo "scale=0; $CPU_LOAD * 100 / $CPU_CORES" | bc)

[ "$CPU_PERCENT" -gt 90 ] && send_alert "🔴 <b>[CRITICAL] CPU</b> - ${HOSTNAME}: ${CPU_PERCENT}%"
[ "$CPU_PERCENT" -gt 80 ] && [ "$CPU_PERCENT" -le 90 ] && \
  send_alert "🟡 <b>[WARNING] CPU</b> - ${HOSTNAME}: ${CPU_PERCENT}%"

# Memory check
MEM_TOTAL=$(grep MemTotal /proc/meminfo | awk '{print $2}')
MEM_AVAIL=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
MEM_PCT=$(echo "scale=0; (($MEM_TOTAL - $MEM_AVAIL) * 100) / $MEM_TOTAL" | bc)

[ "$MEM_PCT" -gt 90 ] && send_alert "🔴 <b>[CRITICAL] Memory</b> - ${HOSTNAME}: ${MEM_PCT}%"
[ "$MEM_PCT" -gt 80 ] && [ "$MEM_PCT" -le 90 ] && \
  send_alert "🟡 <b>[WARNING] Memory</b> - ${HOSTNAME}: ${MEM_PCT}%"

# Disk check
DISK_PCT=$(df / | awk 'NR==2{print $5}' | sed 's/%//')

[ "$DISK_PCT" -gt 90 ] && send_alert "🔴 <b>[CRITICAL] Disk</b> - ${HOSTNAME}: ${DISK_PCT}%"
[ "$DISK_PCT" -gt 80 ] && [ "$DISK_PCT" -le 90 ] && \
  send_alert "🟡 <b>[WARNING] Disk</b> - ${HOSTNAME}: ${DISK_PCT}%"

使用 Cron 设置每 5 分钟检查一次:

chmod +x /opt/monitor/check_resources.sh
crontab -e
# Add:
*/5 * * * * /opt/monitor/check_resources.sh

防止警报疲劳:如果 CPU 持续高负载数小时,每 5 分钟运行一次的脚本会发送数十条消息将您淹没。可以添加带冷却期的锁文件:if [ ! -f /tmp/cpu_alert ] || [ $(( $(date +%s) - $(stat -c %Y /tmp/cpu_alert) )) -gt 3600 ]; then send_alert "..."; touch /tmp/cpu_alert; fi——这样可确保在条件未解除前,同一警报每小时最多触发一次。

每台生产 VPS 必备的警报清单

无论选择哪种工具,以下警报都应在每台承载真实流量的 VPS 上保持启用:

系统资源警报

服务可用性警报

安全警报

在正式依赖之前测试您的警报系统

一个静默失败的错误配置警报系统比没有警报更糟糕——它会制造虚假的安全感。在将系统用于生产工作负载之前,务必进行端到端测试。

测试 Telegram 连通性

curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
  -d chat_id="${CHAT_ID}" \
  -d text="✅ Alert system test from $(hostname) - OK"

模拟高 CPU 负载

sudo apt install stress-ng -y
stress-ng --cpu 4 --timeout 300s &
# Wait 5–15 minutes for alerts to fire based on your configured duration
# Stop the test:
kill %1

检查 Alertmanager 和 Netdata 日志

# Alertmanager
sudo journalctl -u alertmanager -f

# Netdata health log
tail -f /var/log/netdata/health.log

常见问题(FAQ)

CPU 警报应该设置多少阈值?

对于通用服务器,警告阈值设为 80%、严重阈值设为 90% 通常效果较好。建议测量 5–15 分钟的平均值而非瞬时峰值,因为短暂的 CPU 突发是正常现象。如果收到过多警报(警报疲劳),可先将持续时间延长到 10 分钟,再考虑调整阈值。最终根据实际工作负载模式随时间进行微调。

Netdata 与 Prometheus Alertmanager 有何区别?

Netdata 适合只有单台 VPS 且需要一个工具同时提供实时仪表盘和警报的场景——一条命令即可安装并立即运行。Prometheus 加 Alertmanager 适合多服务器环境或需要自定义应用指标的场景,灵活性更高但配置也更复杂。对于刚起步的独立 VPS,Netdata 开箱即用价值更高。

CPU 很高时为什么警报没有发送?

常见原因包括:通知渠道配置错误(Telegram Bot Token 或 Chat ID 有误)、告警规则语法错误导致 Alertmanager 无法加载规则文件、防火墙在 443 端口屏蔽了出站网络,或警报意外处于 Inhibit 或 Silence 状态。请检查 Alertmanager 日志,并在生产环境依赖该系统之前使用 amtool alert add 进行测试。

如何通过 Telegram 机器人发送 VPS 警报?

通过 Telegram 上的 @BotFather 创建机器人并获取 API Token,然后将机器人添加到您希望接收通知的群组或聊天。发送消息后调用 https://api.telegram.org/bot<TOKEN>/getUpdates 获取 Chat ID。在 Alertmanager 接收器或 Netdata 通知设置中填入 Token 和 chat_id 值。部署到生产环境之前务必用 curl 请求验证连接是否正常。

AsiaGB 高性能 KVM VPS

AsiaGB VPS 提供完整 Root 权限,支持 Docker、MySQL、Python 和 Node.js,套餐价格低至每月 500 泰铢。

查看 VPS 套餐

查看泰国VPS主机全部套餐 →