简介
CPU温度是衡量系统健康状况的重要指标之一。过高的CPU温度可能导致系统不稳定、性能下降甚至硬件损坏。实时监控CPU温度有助于及时发现散热问题,预防系统故障。本文将介绍一个实用的Python脚本------CPU温度监控工具,它可以实时监控CPU温度,并在温度过高时发出告警。
功能介绍
这个CPU温度监控工具具有以下核心功能:
- 实时温度监控:实时读取CPU温度传感器数据
- 跨平台支持:支持Windows、Linux和macOS操作系统
- 温度告警:当温度超过设定阈值时发出告警
- 历史数据记录:记录温度变化历史,便于分析
- 可视化图表:生成温度变化趋势图
- 定时监控:支持按指定间隔持续监控CPU温度
- 多核温度监控:支持多核CPU的温度监控
- 风扇转速监控:在支持的系统上监控风扇转速
应用场景
这个工具适用于以下场景:
- 服务器监控:监控服务器CPU温度,预防过热故障
- 高性能计算:在密集计算任务中监控CPU温度
- 系统维护:定期检查系统散热状况
- 故障排查:诊断系统不稳定是否由过热引起
- 超频测试:在CPU超频时监控温度变化
- 环境监控:监控机房或设备环境温度
报错处理
脚本包含了完善的错误处理机制:
- 传感器检测:自动检测可用的温度传感器
- 权限验证:检查是否有足够的权限访问传感器数据
- 硬件兼容性:处理不同硬件平台的兼容性问题
- 数据有效性检查:验证温度数据的有效性
- 异常捕获:捕获并处理运行过程中可能出现的各种异常
- 降级处理:在传感器不可用时提供替代方案
代码实现
python
import os
import sys
import time
import argparse
import json
import platform
from datetime import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from collections import deque
class CPUTemperatureMonitor:
def __init__(self, history_size=100):
self.os_type = platform.system().lower()
self.history_size = history_size
self.temperature_history = deque(maxlen=history_size)
self.timestamp_history = deque(maxlen=history_size)
self.errors = []
self.monitoring = False
def get_cpu_temperature_linux(self):
"""获取Linux系统CPU温度"""
temperatures = {}
# 方法1: 通过sysfs读取温度
try:
hwmon_paths = []
for root, dirs, files in os.walk('/sys/class/hwmon/'):
if 'temp1_input' in files:
hwmon_paths.append(root)
for i, path in enumerate(hwmon_paths):
try:
# 读取温度
with open(os.path.join(path, 'temp1_input'), 'r') as f:
temp_raw = int(f.read().strip())
temp_celsius = temp_raw / 1000.0
# 读取传感器名称
try:
with open(os.path.join(path, 'name'), 'r') as f:
name = f.read().strip()
except:
name = f"Sensor {i+1}"
temperatures[name] = temp_celsius
except Exception as e:
continue
except:
pass
# 方法2: 通过/proc/cpuinfo获取温度(某些系统)
if not temperatures:
try:
with open('/proc/cpuinfo', 'r') as f:
# 注意:/proc/cpuinfo通常不包含温度信息
# 这里只是示例,实际可能需要其他方法
pass
except:
pass
return temperatures
def get_cpu_temperature_windows(self):
"""获取Windows系统CPU温度"""
temperatures = {}
# Windows上获取温度比较复杂,需要第三方库
# 这里提供几种可能的方法
# 方法1: 尝试使用wmi(需要pywin32)
try:
import wmi
c = wmi.WMI(namespace="root\\wmi")
temperature_infos = c.MSAcpi_ThermalZoneTemperature()
for i, sensor in enumerate(temperature_infos):
# 温度以十分之一开尔文为单位
temp_kelvin = sensor.CurrentTemperature / 10.0
temp_celsius = temp_kelvin - 273.15
temperatures[f"Thermal Zone {i+1}"] = temp_celsius
except ImportError:
self.errors.append("缺少wmi库,无法获取Windows温度信息")
except Exception as e:
self.errors.append(f"通过WMI获取温度失败: {e}")
# 方法2: 尝试使用OpenHardwareMonitorLib(需要安装)
if not temperatures:
try:
# 这需要预先安装OpenHardwareMonitor并注册COM组件
# 由于复杂性,这里仅提供框架
pass
except:
pass
return temperatures
def get_cpu_temperature_macos(self):
"""获取macOS系统CPU温度"""
temperatures = {}
# macOS上获取温度也比较复杂
# 可以尝试使用osascript调用系统命令
try:
# 注意:macOS通常不直接暴露温度传感器
# 可能需要第三方工具如iStats
import subprocess
result = subprocess.run(['sysctl', 'machdep.xcpm.cpu_thermal_level'],
capture_output=True, text=True, timeout=10)
if result.returncode == 0:
# 解析输出
output = result.stdout.strip()
# 这里的输出格式可能因系统而异
# 仅作为示例
temperatures['CPU'] = 0.0 # 实际需要解析具体数值
except subprocess.TimeoutExpired:
self.errors.append("获取macOS温度信息超时")
except Exception as e:
self.errors.append(f"获取macOS温度信息失败: {e}")
return temperatures
def get_cpu_temperature(self):
"""获取CPU温度(跨平台)"""
if self.os_type == 'linux':
return self.get_cpu_temperature_linux()
elif self.os_type == 'windows':
return self.get_cpu_temperature_windows()
elif self.os_type == 'darwin': # macOS
return self.get_cpu_temperature_macos()
else:
self.errors.append(f"不支持的操作系统: {self.os_type}")
return {}
def format_temperature(self, temp_celsius):
"""格式化温度显示"""
return f"{temp_celsius:.1f}°C ({temp_celsius * 9/5 + 32:.1f}°F)"
def display_temperature(self, temperatures):
"""显示温度信息"""
# 清屏(兼容不同操作系统)
os.system('cls' if os.name == 'nt' else 'clear')
print("=" * 60)
print("CPU温度监控工具")
print("=" * 60)
print(f"监控时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"操作系统: {self.os_type}")
print()
if temperatures:
print("CPU温度信息:")
for sensor_name, temp in temperatures.items():
print(f" {sensor_name}: {self.format_temperature(temp)}")
# 温度告警
if temp > 80:
print(" ⚠️ 警告: 温度过高!")
elif temp > 70:
print(" ℹ️ 注意: 温度较高")
else:
print("未能获取CPU温度信息")
if self.errors:
print("错误信息:")
for error in self.errors[-3:]: # 显示最近3个错误
print(f" {error}")
print()
print("=" * 60)
print("按 Ctrl+C 停止监控")
def collect_data(self):
"""收集温度数据"""
temperatures = self.get_cpu_temperature()
timestamp = datetime.now()
# 记录到历史数据
if temperatures:
avg_temp = sum(temperatures.values()) / len(temperatures)
self.temperature_history.append(avg_temp)
self.timestamp_history.append(timestamp)
return temperatures
def save_data(self, filename="temperature_data.json"):
"""保存温度数据到文件"""
try:
data = {
'timestamps': [t.isoformat() for t in self.timestamp_history],
'temperatures': list(self.temperature_history),
'os_type': self.os_type,
'record_time': datetime.now().isoformat()
}
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2)
print(f"温度数据已保存到: {filename}")
return True
except Exception as e:
print(f"保存温度数据时出错: {e}")
return False
def generate_chart(self, filename="temperature_chart.png"):
"""生成温度变化图表"""
try:
if len(self.timestamp_history) < 2:
print("数据不足,无法生成图表")
return False
plt.figure(figsize=(12, 6))
plt.plot(self.timestamp_history, self.temperature_history, 'b-', linewidth=1.5)
plt.title('CPU温度变化趋势')
plt.xlabel('时间')
plt.ylabel('温度 (°C)')
plt.grid(True, alpha=0.3)
# 设置温度告警线
plt.axhline(y=70, color='orange', linestyle='--', alpha=0.7, label='高温警告 (70°C)')
plt.axhline(y=80, color='red', linestyle='--', alpha=0.7, label='危险温度 (80°C)')
plt.legend()
# 格式化时间轴
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
plt.gca().xaxis.set_major_locator(mdates.MinuteLocator(interval=5))
plt.setp(plt.gca().xaxis.get_majorticklabels(), rotation=45)
plt.tight_layout()
plt.savefig(filename, dpi=300, bbox_inches='tight')
plt.close()
print(f"温度图表已保存到: {filename}")
return True
except Exception as e:
print(f"生成温度图表时出错: {e}")
return False
def check_temperature_alert(self, temperatures, threshold=80):
"""检查温度告警"""
alerts = []
for sensor_name, temp in temperatures.items():
if temp > threshold:
alerts.append({
'sensor': sensor_name,
'temperature': temp,
'threshold': threshold,
'time': datetime.now().isoformat()
})
if alerts:
print("\n🚨 温度告警!")
for alert in alerts:
print(f" {alert['sensor']}: {self.format_temperature(alert['temperature'])} "
f"(阈值: {alert['threshold']}°C)")
return alerts
def start_monitoring(self, interval=5, duration=None, alert_threshold=80,
save_data=False, chart_file=None):
"""开始监控"""
self.monitoring = True
start_time = time.time()
try:
while self.monitoring:
# 收集数据
temperatures = self.collect_data()
# 显示温度
self.display_temperature(temperatures)
# 检查告警
if temperatures:
self.check_temperature_alert(temperatures, alert_threshold)
# 保存数据
if save_data and len(self.temperature_history) % 10 == 0: # 每10次保存一次
self.save_data()
# 检查是否达到指定时长
if duration and (time.time() - start_time) >= duration:
break
# 等待下次监控
time.sleep(interval)
except KeyboardInterrupt:
print("\n\n停止监控...")
finally:
self.monitoring = False
# 生成图表
if chart_file:
self.generate_chart(chart_file)
# 保存最终数据
if save_data:
self.save_data()
print("监控已停止")
def main():
parser = argparse.ArgumentParser(description="CPU温度监控工具")
parser.add_argument("-i", "--interval", type=int, default=5,
help="监控间隔(秒,默认:5)")
parser.add_argument("-d", "--duration", type=int,
help="监控时长(秒,不指定则持续监控)")
parser.add_argument("-t", "--threshold", type=float, default=80.0,
help="温度告警阈值(°C,默认:80)")
parser.add_argument("-s", "--save-data", action="store_true",
help="保存温度数据到文件")
parser.add_argument("-c", "--chart", help="生成温度图表到指定文件")
parser.add_argument("--list-sensors", action="store_true",
help="列出可用的温度传感器")
args = parser.parse_args()
# 检查必要的依赖
if args.list_sensors and platform.system().lower() == 'windows':
try:
import wmi
except ImportError:
print("警告: 缺少wmi库,无法列出Windows传感器")
try:
monitor = CPUTemperatureMonitor()
# 列出传感器
if args.list_sensors:
temperatures = monitor.get_cpu_temperature()
print("可用的温度传感器:")
if temperatures:
for sensor_name, temp in temperatures.items():
print(f" {sensor_name}: {monitor.format_temperature(temp)}")
else:
print(" 未找到可用的温度传感器")
return
# 开始监控
monitor.start_monitoring(
interval=args.interval,
duration=args.duration,
alert_threshold=args.threshold,
save_data=args.save_data,
chart_file=args.chart
)
except KeyboardInterrupt:
print("\n\n用户中断操作")
except Exception as e:
print(f"程序执行出错: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
使用方法
安装依赖
在使用此脚本之前,可能需要安装必要的库:
bash
# Windows系统(可选,用于更好的温度监控)
pip install pywin32 wmi
# 生成图表需要
pip install matplotlib
基本使用
bash
# 基本用法,每5秒刷新一次
python cpu_temp_monitor.py
# 设置监控间隔为10秒
python cpu_temp_monitor.py -i 10
# 监控60秒后自动停止
python cpu_temp_monitor.py -d 60
# 设置告警阈值为75°C
python cpu_temp_monitor.py -t 75
# 保存温度数据到文件
python cpu_temp_monitor.py -s
# 生成温度变化图表
python cpu_temp_monitor.py -c temperature.png
# 列出可用的温度传感器
python cpu_temp_monitor.py --list-sensors
命令行参数说明
-i, --interval: 监控间隔(秒),默认5秒-d, --duration: 监控时长(秒),不指定则持续监控-t, --threshold: 温度告警阈值(°C),默认80°C-s, --save-data: 保存温度数据到文件-c, --chart: 生成温度图表到指定文件--list-sensors: 列出可用的温度传感器
使用示例
- 持续监控CPU温度:
bash
python cpu_temp_monitor.py
- 监控并保存数据:
bash
python cpu_temp_monitor.py -i 10 -d 300 -s -c temp_trend.png
- 设置较低的告警阈值:
bash
python cpu_temp_monitor.py -t 70
总结
这个CPU温度监控工具提供了一个跨平台的CPU温度监控解决方案,能够实时显示CPU温度并在温度过高时发出告警。它支持数据持久化和可视化图表生成,适用于服务器监控、系统维护和故障排查等多种场景。通过这个工具,用户可以及时了解CPU的温度状况,预防因过热导致的系统问题,确保系统的稳定运行。
需要注意的是,不同操作系统的温度获取方法有所不同,某些平台可能需要安装额外的库或工具才能获取准确的温度数据。在实际使用中,建议根据具体的硬件平台和操作系统选择合适的实现方式。