服务器磁盘空间的使用情况直接关系到服务的稳定运行,当磁盘使用率过高时可能引发服务宕机、数据写入失败等问题。传统的手动巡检方式不仅效率低下,还难以及时捕捉磁盘的异常增长趋势,因此实现自动化的磁盘监控和趋势预测十分必要。

方案整体设计
整个脚本方案分为三个核心模块:磁盘数据采集模块、趋势预测模块、报告生成模块。首先定时采集服务器的磁盘使用数据并存储到本地文件,然后基于历史数据训练预测模型,最后将分析结果和可视化图表整合为PDF报告,同时支持设置阈值触发预警通知。
环境依赖准备
运行该脚本需要安装以下Python第三方库,可通过pip命令一键安装:
- psutil:用于获取系统磁盘使用信息
- numpy:用于数值计算和矩阵运算
- matplotlib:用于生成磁盘使用趋势图表
- reportlab:用于生成PDF格式的预测报告
安装命令如下:
pip install psutil numpy matplotlib reportlab
磁盘数据采集实现
使用psutil库可以跨平台获取磁盘的分区信息和使用率,我们需要定时采集指定磁盘分区的已用空间、总空间、使用率等数据,并追加存储到CSV文件中作为历史数据。
核心采集代码
以下代码实现了磁盘数据的采集和存储功能:
import psutil
import csv
import time
from datetime import datetime
# 配置需要监控的磁盘分区,Linux下为/,Windows下为C:
MONITOR_DISK = "/"
# 数据存储文件路径
DATA_FILE = "disk_usage_history.csv"
def collect_disk_data():
# 获取磁盘使用情况
disk_info = psutil.disk_usage(MONITOR_DISK)
# 提取需要的数据:时间、总空间(GB)、已用空间(GB)、使用率
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
total_gb = disk_info.total / (1024 ** 3)
used_gb = disk_info.used / (1024 ** 3)
usage_percent = disk_info.percent
# 写入CSV文件,首次写入时添加表头
try:
with open(DATA_FILE, "a", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
# 检查文件是否为空,为空则写表头
if f.tell() == 0:
writer.writerow(["采集时间", "总空间(GB)", "已用空间(GB)", "使用率(%)"])
writer.writerow([current_time, round(total_gb, 2), round(used_gb, 2), usage_percent])
print(f"{current_time} 磁盘数据采集完成,当前使用率:{usage_percent}%")
except Exception as e:
print(f"数据采集失败:{str(e)}")
if __name__ == "__main__":
# 测试采集一次数据
collect_disk_data()
磁盘增长趋势预测实现
这里采用简单的线性回归算法对磁盘使用趋势进行预测,将采集时间转换为数值特征,以已用空间为预测目标,训练模型后预测未来7天的磁盘使用情况。
预测核心代码
以下代码实现了基于历史数据的趋势预测功能:
import csv
import numpy as np
from datetime import datetime, timedelta
def predict_disk_usage(days=7):
# 读取历史数据
times = []
used_spaces = []
try:
with open("disk_usage_history.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
# 将时间字符串转换为时间戳数值
time_obj = datetime.strptime(row["采集时间"], "%Y-%m-%d %H:%M:%S")
times.append(time_obj.timestamp())
used_spaces.append(float(row["已用空间(GB)"]))
except Exception as e:
print(f"读取历史数据失败:{str(e)}")
return None
if len(times) < 2:
print("历史数据不足,无法预测")
return None
# 转换为numpy数组
X = np.array(times).reshape(-1, 1)
y = np.array(used_spaces)
# 训练线性回归模型
# 计算斜率和截距:y = kx + b
X_mean = np.mean(X)
y_mean = np.mean(y)
numerator = np.sum((X - X_mean) * (y - y_mean))
denominator = np.sum((X - X_mean) ** 2)
k = numerator / denominator
b = y_mean - k * X_mean
# 预测未来days天的磁盘使用情况
last_time = times[-1]
predictions = []
for i in range(1, days + 1):
future_time = last_time + i * 86400 # 加i天的秒数
future_used = k * future_time + b
future_date = datetime.fromtimestamp(last_time) + timedelta(days=i)
predictions.append({
"日期": future_date.strftime("%Y-%m-%d"),
"预测已用空间(GB)": round(future_used, 2)
})
return {
"斜率": round(k, 6),
"每日增长量(GB)": round(k * 86400, 2),
"预测结果": predictions
}
if __name__ == "__main__":
result = predict_disk_usage(7)
if result:
print(f"磁盘每日增长量:{result['每日增长量(GB)']} GB")
print("未来7天预测结果:")
for item in result["预测结果"]:
print(f"{item['日期']}: {item['预测已用空间(GB)']} GB")
预测报告生成实现
报告生成模块需要将历史趋势图表和预测结果整合为PDF文件,同时支持设置使用率阈值,当预测使用率超过阈值时添加预警提示。
报告生成核心代码
以下代码实现了PDF报告的生成功能:
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import csv
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from datetime import datetime
# 注册中文字体,避免中文乱码,需要提前准备SimHei.ttf字体文件
try:
pdfmetrics.registerFont(TTFont("SimHei", "SimHei.ttf"))
except:
print("未找到SimHei字体,报告中文可能显示异常")
def generate_trend_chart():
# 读取历史数据
dates = []
used_spaces = []
try:
with open("disk_usage_history.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
dates.append(row["采集时间"])
used_spaces.append(float(row["已用空间(GB)"]))
except Exception as e:
print(f"读取数据失败:{str(e)}")
return None
# 生成趋势图
plt.figure(figsize=(10, 4))
plt.plot(dates, used_spaces, marker="o", label="历史使用量")
plt.xticks(rotation=45)
plt.xlabel("采集时间")
plt.ylabel("已用空间(GB)")
plt.title("磁盘使用趋势图")
plt.legend()
plt.tight_layout()
chart_path = "disk_trend.png"
plt.savefig(chart_path)
plt.close()
return chart_path
def generate_pdf_report(predict_result, threshold=90):
# 生成趋势图
chart_path = generate_trend_chart()
if not chart_path:
print("趋势图生成失败,无法生成报告")
return
# 创建PDF文件
report_name = f"磁盘预测报告_{datetime.now().strftime('%Y%m%d')}.pdf"
c = canvas.Canvas(report_name, pagesize=A4)
width, height = A4
# 设置字体
c.setFont("SimHei", 16)
c.drawString(2*cm, height-2*cm, "服务器磁盘增长趋势预测报告")
# 写入报告生成时间
c.setFont("SimHei", 10)
c.drawString(2*cm, height-3*cm, f"报告生成时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
# 插入趋势图
if chart_path:
c.drawImage(chart_path, 2*cm, height-12*cm, width=16*cm, height=8*cm)
# 写入预测结果
c.setFont("SimHei", 12)
c.drawString(2*cm, height-14*cm, f"磁盘每日增长量:{predict_result['每日增长量(GB)']} GB")
# 写入未来7天预测数据
c.drawString(2*cm, height-15*cm, "未来7天磁盘使用预测:")
y_position = height-16*cm
for item in predict_result["预测结果"]:
c.drawString(3*cm, y_position, f"{item['日期']}: 预测已用空间 {item['预测已用空间(GB)']} GB")
y_position -= 1*cm
# 预警提示
c.setFont("SimHei", 12)
last_used = float(predict_result["预测结果"][-1]["预测已用空间(GB)"])
# 读取总空间计算使用率
try:
with open("disk_usage_history.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
rows = list(reader)
total_space = float(rows[-1]["总空间(GB)"])
predict_percent = round(last_used / total_space * 100, 2)
if predict_percent > threshold:
c.setFillColorRGB(1, 0, 0)
c.drawString(2*cm, y_position-1*cm, f"预警:未来7天磁盘使用率预计达到{predict_percent}%,超过{threshold}%阈值,请及时扩容!")
except Exception as e:
print(f"计算使用率失败:{str(e)}")
c.save()
print(f"报告生成完成:{report_name}")
if __name__ == "__main__":
# 先获取预测结果
predict_result = predict_disk_usage(7)
if predict_result:
generate_pdf_report(predict_result)
定时任务配置
实现自动化运行需要将数据采集脚本配置为定时任务,Linux系统可使用crontab,Windows系统可使用任务计划程序。
Linux crontab配置示例
编辑crontab配置:
crontab -e
添加以下内容,表示每小时执行一次数据采集脚本:
0 * * * * /usr/bin/python3 /path/to/collect_disk_data.py >> /var/log/disk_monitor.log 2>&1
每天凌晨执行一次预测和报告生成脚本:
0 0 * * * /usr/bin/python3 /path/to/generate_report.py >> /var/log/disk_monitor.log 2>&1
注意事项
- 历史数据文件需要定期清理,避免占用过多磁盘空间,可只保留最近30天的数据
- 线性回归模型适用于短期趋势预测,若磁盘使用存在周期性波动,可替换为ARIMA等时间序列预测模型
- 生产环境中建议添加邮件或企业微信预警通知,当预测使用率超过阈值时及时推送消息给运维人员
- 若监控多台服务器,可将数据采集脚本部署到各节点,通过统一的服务端汇总数据后生成报告