高效编写CPU占用监控脚本:从入门到实战指南
📖 目录导读
为什么需要监控CPU占用?
服务器或应用程序的CPU占用过高会导致响应变慢、服务中断甚至系统崩溃,编写监控脚本能帮助你:

- 实时发现异常波动(如挖矿程序、死循环进程)
- 自动触发告警或重启服务
- 分析历史负载趋势,为扩容提供依据
✅ 关键数据:根据Google运维报告,75%的服务中断与CPU资源耗尽直接相关。
监控脚本的核心原理
所有监控脚本都基于以下机制:
数据来源:
- Linux:
/proc/stat文件(总CPU使用)、/proc/pid/stat(进程级) - Windows:
Get-CounterPowerShell命令或WMI接口 - 跨平台:
psutilPython库(推荐)
计算逻辑:
- 读取CPU总时间(user+system+idle+...)
- 间隔1-5秒再次读取
- 用公式:
使用率 = (新总时间 - 旧总时间) / (新总时间 - 旧总时间) × 100
5种常用脚本实现方式
Bash+Top命令(最轻量)
#!/bin/bash
CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
echo "$(date '+%Y-%m-%d %H:%M:%S') CPU使用率: $CPU%"
if (( $(echo "$CPU > 90" | bc -l) )); then
echo "警告:CPU占用过高!" | systemd-cat -p crit
fi
适合场景:临时快速检查,无第三方依赖
Python+psutil(最强大)
import psutil
import time
def monitor_cpu(interval=1, threshold=90):
cpu_percent = psutil.cpu_percent(interval=interval, percpu=True)
avg = sum(cpu_percent) / len(cpu_percent)
print(f"平均CPU: {avg:.1f}%, 各核心: {cpu_percent}")
if avg > threshold:
# 发送告警:例如邮件、钉钉Webhook
alert_process(threshold, avg, "High CPU Alert")
return avg
# 持续监控
while True:
monitor_cpu()
time.sleep(5)
优点:跨平台、可获取进程级数据、支持告警集成
Go+gopsutil(高性能)
package main
import (
"fmt"
"github.com/shirou/gopsutil/v3/cpu"
"time"
)
func main() {
for {
percent, _ := cpu.Percent(time.Second, false)
fmt.Printf("CPU使用率: %.2f%%\n", percent[0])
time.Sleep(3 * time.Second)
}
}
优点:适合生产级高并发监控,资源开销低
Windows PowerShell
while($true) {
$cpu = (Get-Counter "\Processor(_Total)\% Processor Time").CounterSamples.CookedValue
Write-Host "$(Get-Date):CPU $cpu%"
if($cpu -gt 90) { Write-Warning "CPU超过90%!" }
Start-Sleep -Seconds 2
}
Prometheus+Grafana(企业级方案)
推荐使用Prometheus官方 node_exporter 采集,脚本只需暴露指标:
from prometheus_client import start_http_server, Gauge
import psutil, time
cpu_gauge = Gauge('cpu_usage_percent', 'CPU使用率')
start_http_server(9100)
while True:
cpu_gauge.set(psutil.cpu_percent())
time.sleep(5)
实战问答:常见问题与解决方案
Q1:如何监控特定进程的CPU占用?
# 方法一:psutil.process_iter()
for proc in psutil.process_iter(['pid', 'name']):
if 'nginx' in proc.info['name']:
cpu_usage = proc.cpu_percent(interval=0.5)
print(f"{proc.info['name']}(PID:{proc.info['pid']}) CPU: {cpu_usage}%")
Q2:监控脚本本身占用CPU过高怎么办?
- 缩短采样间隔(建议≥1秒)
- 使用事件驱动而非轮询(如
psutil.cpu_percent的percpu=True模式) - 生产环境用C语言或Go替代Python脚本
Q3:如何在容器(Docker)中监控宿主机CPU?
# 需要挂载/sys/fs/cgroup docker run -v /sys/fs/cgroup:/sys/fs/cgroup:ro your-monitor-image # 或使用cAdvisor方案
Q4:脚本运行时报错“Read-only file system”?
排查方向:
ls -la /proc/stat # 确认权限 mount | grep proc # 检查/proc挂载 # 解决方案:使用read()而非open()直接读取
性能优化与生产环境部署建议
⚡ 性能对比表
| 方案 | 内存占用 | CPU开销 | 精度 | 部署复杂度 |
|---|---|---|---|---|
| Bash+top | <1MB | 极低 | 一般 | 简单 |
| Python+psutil | 20-50MB | 低 | 高 | 中等 |
| Go+gopsutil | 5-15MB | 极低 | 高 | 较高 |
| Prometheus节点 | 30-50MB | 低 | 极高 | 复杂 |
🔧 部署最佳实践
- 持久化存储:每次采样写入CSV/InfluxDB,保留至少30天数据
- 分级告警:80%黄色告警,95%紧急告警,99%直接重启
- 日志轮转:使用
logrotate管理,避免磁盘写满 - 安全加固:
- 脚本权限设为
chmod 700 - 使用非root用户运行
- 输出避免硬编码敏感信息
- 脚本权限设为
📅 计划任务示例(Crontab)
# 每5分钟检查一次,记录到日志 */5 * * * * /opt/scripts/cpu_monitor.sh >> /var/log/cpu_monitor.log 2>&1
通过以上方法,你可以根据实际需求选择最合适的CPU监控脚本实现,从简单的Bash一行命令到完整的Prometheus+Grafana可视化方案,关键在于平衡精度、性能和运维成本,建议先用Python原型验证,再根据性能瓶颈升级到Go或系统级方案。