- 创建 RRD 数据库:定义数据结构,例如数据如何被存储、如何聚合(如平均值、最大值)。
- 更新 RRD 数据库:定期将新的数据点存入数据库。
- 从 RRD 数据库生成图表:将存储的数据可视化,生成 PNG、SVG 等格式的图片。
第零步:安装 rrdtool
你需要确保系统上安装了 rrdtool 的命令行工具和 Python 的绑定库。

安装 rrdtool 命令行工具
-
在 Debian/Ubuntu 上:
sudo apt-get update sudo apt-get install rrdtool
-
在 CentOS/RHEL/Fedora 上:
sudo yum install rrdtool # 或者对于较新的系统 sudo dnf install rrdtool
-
在 macOS 上 (使用 Homebrew):
brew install rrdtool
安装 Python 绑定库
Python 的 rrdtool 库通常通过 pip 安装。

pip install rrdtool
第一步:创建 RRD 数据库 (rrdtool.create)
在存储任何数据之前,你必须先创建一个 RRD 文件,这个文件定义了你的数据结构,核心概念包括:
- DS (Data Source): 数据源,定义了你存储的数据的类型,最常用的是
GAUGE(瞬时值,如温度)、COUNTER(计数器,如网络字节数,只会增加)、DERIVE(导出值,如速度,可以增加或减少)。 - RRA (Round Robin Archive): 存储数据的方式,它定义了数据点如何被聚合和存储,你可以存储每5秒一个原始数据点,持续1小时;然后存储每5分钟的平均值,持续1天;再存储每小时的平均值,持续一个月。
示例代码:创建一个用于存储 CPU 使用率的 RRD 数据库
假设我们想每分钟记录一次 CPU 使用率(百分比),并保留以下数据:
- 每分钟的平均值,保留 1 天 (1440 个点)。
- 每小时的最大值,保留 1 周 (168 个点)。
- 每天的平均值,保留 1 年 (365 个点)。
import rrdtool
import os
# 定义 RRD 文件名
rrd_file = 'cpu_usage.rrd'
# 如果文件已存在,先删除它以便于测试
if os.path.exists(rrd_file):
os.remove(rrd_file)
# 定义创建 RRD 的参数
# 'start': 时间戳,表示数据库的起始时间,我们使用当前时间减去10秒,以确保第一个数据点能被接受。
# '--step': 默认的数据收集间隔,这里是60秒。
# 'DS:cpu_usage:GAUGE:120:0:100': 定义数据源
# - DS:cpu_usage: 数据源的名称是 "cpu_usage"
# - GAUGE: 数据类型是瞬时值
# - 120: 心跳时间,如果在120秒内没有收到新数据,该数据点将被标记为未知 (U)。
# - 0:100: 最小值和最大值,超出这个范围的数据将被视为无效。
# 'RRA:AVERAGE:0.5:1:1440': 定义归档
# - AVERAGE: 聚合类型是平均值
# - 0.5: xff (x-file factor),当在聚合窗口内未知数据点的比例超过这个值时,结果将是未知。
# - 1: 聚合因子,将 1 个基本数据点(60秒)聚合成 1 个数据点。
# - 1440: 保留的归档数据点数量,1分钟一个点 * 1440点 = 1440分钟 = 1天。
# 'RRA:MAX:0.5:60:168': 每小时的最大值 (60分钟聚合,保留168小时)
# 'RRA:AVERAGE:0.5:1440:365': 每天的平均值 (1440分钟=24小时聚合,保留365天)
rrdtool.create(
rrd_file,
'--start', 'now-10s',
'--step', '60',
'DS:cpu_usage:GAUGE:120:0:100',
'RRA:AVERAGE:0.5:1:1440', # 1天, 每分钟平均值
'RRA:MAX:0.5:60:168', # 1周, 每小时最大值
'RRA:AVERAGE:0.5:1440:365' # 1年, 每天平均值
)
print(f"RRD 文件 '{rrd_file}' 创建成功。")
运行这段代码后,你会在当前目录下看到一个名为 cpu_usage.rrd 的文件,这个文件现在是一个空的、结构化的数据库。

第二步:更新 RRD 数据库 (rrdtool.update)
我们需要模拟数据并定期更新到 RRD 文件中,在实际应用中,这部分代码会由你的监控脚本定时执行(使用 cron 或 schedule 库)。
示例代码:更新 CPU 使用率数据
import rrdtool
import time
import random
rrd_file = 'cpu_usage.rrd'
# 模拟更新10次,每次间隔60秒
for i in range(10):
# 获取当前时间戳 (格式: N)
current_time = 'N'
# 生成一个随机的 CPU 使用率 (0-100之间)
cpu_value = random.uniform(10, 90)
# 构建更新命令
# 'update <rrd_file> <timestamp>:<value>'
update_string = f"{current_time}:{cpu_value:.2f}"
try:
# 执行更新
rrdtool.update(rrd_file, update_string)
print(f"更新成功: 时间={current_time}, CPU使用率={cpu_value:.2f}%")
except rrdtool.error as e:
print(f"更新失败: {e}")
# 等待60秒
time.sleep(60)
print("数据更新完成。")
运行这个脚本后,你的 cpu_usage.rrd 文件就填充了10个数据点。
第三步:生成图表 (rrdtool.graph)
这是最有趣的部分——将数据可视化。rrdtool.graph 函数非常强大,可以生成各种复杂的图表。
示例代码:生成一个简单的 CPU 使用率折线图
import rrdtool
import os
rrd_file = 'cpu_usage.rrd'
output_png = 'cpu_usage_graph.png'
# 检查RRD文件是否存在
if not os.path.exists(rrd_file):
print(f"错误: RRD 文件 '{rrd_file}' 不存在,请先创建并更新它。")
exit()
# 定义图表参数
# 'graph <output_file> <options> <definition> <instruction>'
# <options>: 全局选项,如标题、大小、单位等
# <definition>: 定义图表中要显示的数据(从哪个RRA中取什么数据)
# <instruction>: 定义图表中的线条、区域等元素
graph_args = [
output_png,
# --- 全局选项 ---
'--title', 'CPU 使用率监控',
'--width', '800',
'--height', '400',
'--start', '-1h', # 图表显示从1小时前开始的数据
'--end', 'now', # 到现在为止
'--vertical-label', 'CPU 使用率 (%)',
'--rigid', # Y轴不会根据数据动态伸缩,而是固定在0-100
'--upper-limit', '100', # Y轴上限
'--lower-limit', '0', # Y轴下限
'--alt-autoscale', # 当数据范围不满足 --upper/--lower-limit 时,自动调整
# --- 数据定义 ---
# 'DEF:<name>=<rrd_file>:<ds_name>:< consolidation_function>'
# DEF:my_cpu_data=cpu_usage.rrd:cpu_usage:AVERAGE
# - 定义一个名为 'my_cpu_data' 的数据,它从 'cpu_usage.rrd' 文件的 'cpu_usage' 数据源中,
# 取 'AVERAGE' (平均值) 类型的数据。
'DEF:my_cpu_data=' + rrd_file + ':cpu_usage:AVERAGE',
# --- 图表元素 ---
# 'LINE1/2/3:<data_source>#<color>:<label>'
# 'AREA:<data_source>#<color>:<label>'
'LINE1:my_cpu_data#00FF00:CPU使用率', # 绿色实线
'GPRINT:my_cpu_data:LAST:当前值: %5.2lf %%', # 在图上打印最后一个值
'GPRINT:my_cpu_data:AVERAGE:平均值: %5.2lf %%', # 打印平均值
'GPRINT:my_cpu_data:MAX:最大值: %5.2lf %%\n' # 打印最大值并换行
]
try:
# 生成图表
rrdtool.graph(*graph_args)
print(f"图表已成功生成并保存为 '{output_png}'")
except rrdtool.error as e:
print(f"生成图表失败: {e}")
运行这段代码后,你会得到一个名为 cpu_usage_graph.png 的图片,显示过去一小时的 CPU 使用率折线图,并在图上标注了当前值、平均值和最大值。
高级示例:组合多个数据源
假设我们不仅监控 CPU,还监控内存使用率,并将它们画在同一个图表上进行对比。
创建一个包含两个数据源的 RRD 文件
# (创建数据库的代码)
rrdtool.create(
'system_stats.rrd',
'--start', 'now-10s',
'--step', '60',
# CPU 数据源
'DS:cpu_usage:GAUGE:120:0:100',
# 内存数据源 (假设总内存为16GB,使用百分比)
'DS:mem_usage:GAUGE:120:0:100',
# ... RRAs ...
'RRA:AVERAGE:0.5:1:1440',
'RRA:MAX:0.5:60:168',
'RRA:AVERAGE:0.5:1440:365'
)
更新两个数据源
# (更新数据的代码)
for i in range(10):
current_time = 'N'
cpu_value = random.uniform(10, 90)
mem_value = random.uniform(30, 80)
# 一次性更新多个数据源
update_string = f"{current_time}:{cpu_value:.2f}:{mem_value:.2f}"
rrdtool.update('system_stats.rrd', update_string)
time.sleep(60)
生成组合图表
# (生成图表的代码)
rrdtool.graph(
'system_stats_graph.png',
'--title', '系统资源监控',
'--width', '800',
'--height', '400',
'--start', '-1h',
'--end', 'now',
'--vertical-label', '使用率 (%)',
'--rigid',
'--upper-limit', '100',
'--lower-limit', '0',
# 定义两个数据源
'DEF:cpu_data=system_stats.rrd:cpu_usage:AVERAGE',
'DEF:mem_data=system_stats.rrd:mem_usage:AVERAGE',
# CPU 用绿色实线表示,并填充半透明区域
'LINE1:cpu_data#00FF00:CPU',
'AREA:cpu_data#00FF0033:CPU', # #33 是 20% 的透明度
# 内存用蓝色虚线表示
'LINE1:mem_data#0000FF:内存',
# 添加图例
'HRULE:50#FF000050:"警告线"', # 添加一条50%的红色虚线作为警告
)
这个高级示例展示了如何处理多个指标,并通过不同的线条样式和颜色来区分它们,甚至可以添加参考线。
| 功能 | rrdtool 函数 |
描述 |
|---|---|---|
| 创建 | rrdtool.create() |
定义数据库结构 (DS, RRA) |
| 更新 | rrdtool.update() |
向数据库中插入新的数据点 |
| 查询 | rrdtool.fetch() |
从数据库中提取原始数据(用于程序处理) |
| 画图 | rrdtool.graph() |
将数据渲染成图片 (PNG, SVG 等) |
rrdtool 的核心优势在于其高效的存储引擎(固定大小的环形数据库,不会无限增长)和强大的内置聚合功能,使其成为网络和系统监控领域的黄金标准,通过 Python 绑定,你可以轻松地将 rrdtool 集成到你的自动化监控和运维脚本中。
