MIB Viewer

RRDtool: Installing It, Polling SNMP, and Building Graphs

Last updated October 20, 2026

RRDtool (Round-Robin Database tool) is a data-logging and graphing system for time-series data, such as values sampled from SNMP counters at a fixed interval. It stores samples in a fixed-size database file and renders them as line or area graphs. This guide covers its history, its data model, installation, command-line usage, and an example of polling SNMP data and graphing it.

History

RRDtool was written by Tobias Oetiker, a systems engineer at ETH Zurich, as a successor to MRTG (Multi Router Traffic Grapher), a tool he released in 1995. MRTG polled a router's interface counters over SNMP and generated a bandwidth graph showing inbound traffic above a zero line and outbound traffic below it. MRTG stored samples in a plain-text log file that grew without bound and had to be read in full on every update.

RRDtool was first released in 1999. It replaced MRTG's logging and graphing code with a standalone library and a fixed-size database format, the round-robin database, so that update time and file size do not increase with the amount of history retained. MRTG was later modified to use RRDtool for storage. Other software built on RRDtool followed, including Cacti, Smokeping, Munin, and the RRD output plugin of collectd. RRDtool is maintained by Oetiker and a small group of contributors and is packaged by most Linux distributions.

Data model

An RRDtool database stores one or more named data sources (DS), each with a declared type:

  • GAUGE - a value used as-is, such as a temperature or a percentage.
  • COUNTER - a value that increases monotonically and wraps at a fixed maximum, such as an SNMP interface octet counter. RRDtool stores the rate of change per second rather than the raw value, and accounts for the wraparound.
  • DERIVE - like COUNTER, but the value is allowed to decrease; a decrease is treated as unknown unless a minimum is configured.
  • ABSOLUTE - a counter that is reset to zero after each read.

Each DS has a heartbeat, the maximum number of seconds between updates before the interval is recorded as unknown.

Data is retained in one or more RRAs (Round Robin Archives), each defined by a consolidation function (AVERAGE, MIN, MAX, or LAST), the number of base time steps consolidated into one row, and the number of rows kept. When an archive is full, the oldest row is overwritten by the newest, which keeps the file at a fixed size. A database typically defines several RRAs at increasing step sizes, so recent data is kept at full resolution and older data is kept at a coarser resolution.

Installation

# Debian / Ubuntu
sudo apt update
sudo apt install rrdtool

# RHEL / CentOS / Fedora
sudo dnf install rrdtool
# (older systems: sudo yum install rrdtool)

# macOS (Homebrew)
brew install rrdtool

This installs the rrdtool command-line program. Bindings for the same underlying library exist for Perl (the RRDs module, included with RRDtool), Python (the rrdtool PyPI package), and PHP (the pecl-rrd extension).

Creating a database

The following command creates a database with two COUNTER data sources, in and out, at a 300-second step, with four AVERAGE and four MAX archives:

rrdtool create /var/lib/rrd/switch1-eth0.rrd \
  --start now-10s \
  --step 300 \
  DS:in:COUNTER:600:0:U \
  DS:out:COUNTER:600:0:U \
  RRA:AVERAGE:0.5:1:600 \
  RRA:AVERAGE:0.5:6:700 \
  RRA:AVERAGE:0.5:24:775 \
  RRA:AVERAGE:0.5:288:797 \
  RRA:MAX:0.5:1:600 \
  RRA:MAX:0.5:6:700 \
  RRA:MAX:0.5:24:775 \
  RRA:MAX:0.5:288:797

DS:in:COUNTER:600:0:U declares a data source named in, of type COUNTER, with a 600-second heartbeat, a minimum of 0, and no declared maximum (U, unknown). RRA:AVERAGE:0.5:1:600 defines an archive using the AVERAGE function, an xff of 0.5 (the maximum fraction of unknown values allowed in a consolidation period), one base step per row, and 600 rows - at a 300-second step, this holds about two days of 5-minute data. The following RRA lines consolidate 6, 24, and 288 steps per row, holding about two weeks at 30 minutes, two months at 2 hours, and two years at 1 day. --start must precede the timestamp of the first update.

Updating a database

rrdtool update /var/lib/rrd/switch1-eth0.rrd N:184523981:95820142

An update supplies a timestamp (N for the current time, or a Unix timestamp) and one value per data source, in the order the data sources were declared. Timestamps must increase with each update. For a COUNTER data source, the value supplied is the raw cumulative counter; RRDtool computes the rate from the difference between the new and previous values divided by the elapsed time.

Polling SNMP data

Interface traffic counters are defined in IF-MIB, indexed by ifIndex. The 32-bit ifInOctets and ifOutOctets counters wrap at 4 GB, which on a link above about 100 Mbit/s can occur within minutes. The 64-bit counters ifHCInOctets and ifHCOutOctets, from ifXTable, are used instead on faster interfaces. The Finding OIDs guide covers finding an interface's ifIndex by walking ifDescr. The Generating SNMP Commands guide covers generating an snmpget/snmpwalk command for a specific object from its page in MIB Viewer. The Using net-snmp guide covers installing the snmpget/snmpwalk tools used below.

The following script retrieves both counters for a single interface and updates the database created above:

#!/bin/sh
# /usr/local/bin/poll-switch1-eth0.sh
HOST=switch1.example.net
COMMUNITY=public
IFINDEX=5

IN=$(snmpget -v2c -c "$COMMUNITY" -Oqv "$HOST" IF-MIB::ifHCInOctets."$IFINDEX")
OUT=$(snmpget -v2c -c "$COMMUNITY" -Oqv "$HOST" IF-MIB::ifHCOutOctets."$IFINDEX")

rrdtool update /var/lib/rrd/switch1-eth0.rrd N:"$IN":"$OUT"

A cron entry runs the script on the same interval as the database's step:

# crontab
*/5 * * * * /usr/local/bin/poll-switch1-eth0.sh

The -Oqv flags to snmpget print only the numeric value, without the OID or type prefix, so the output can be used directly. Polling more than a few interfaces is typically done with a single snmpbulkwalk of the ifHCInOctets and ifHCOutOctets columns, parsed to extract each ifIndex of interest, rather than one snmpget per counter.

Building a graph

rrdtool graph /var/www/html/graphs/switch1-eth0.png \
  --start -1d \
  --width 600 --height 200 \
  --title "switch1 eth0 traffic" \
  --vertical-label "bits/sec" \
  DEF:inoctets=/var/lib/rrd/switch1-eth0.rrd:in:AVERAGE \
  DEF:outoctets=/var/lib/rrd/switch1-eth0.rrd:out:AVERAGE \
  CDEF:inbits=inoctets,8,* \
  CDEF:outbits=outoctets,8,* \
  CDEF:outbits_neg=outbits,-1,* \
  AREA:inbits#00CC00:"In " \
  GPRINT:inbits:LAST:"Cur\: %6.2lf %Sbit/s" \
  GPRINT:inbits:AVERAGE:"Avg\: %6.2lf %Sbit/s" \
  GPRINT:inbits:MAX:"Max\: %6.2lf %Sbit/s\n" \
  AREA:outbits_neg#0000CC:"Out" \
  GPRINT:outbits:LAST:"Cur\: %6.2lf %Sbit/s" \
  GPRINT:outbits:AVERAGE:"Avg\: %6.2lf %Sbit/s" \
  GPRINT:outbits:MAX:"Max\: %6.2lf %Sbit/s\n" \
  HRULE:0#000000

DEF reads a named series from a database file, data source, and consolidation function. CDEF computes a new series from existing ones using reverse Polish notation; inoctets,8,* multiplies the octet rate by 8 to convert it to bits per second, and outbits,-1,* negates the outbound series so it is drawn below the zero line. GPRINT prints a computed statistic - here the last, average, and maximum value over the graphed period - into the legend. A literal colon in GPRINT/COMMENT text must be escaped as \:, since an unescaped colon is a field separator in the graph command syntax. %S applies automatic SI-prefix scaling to the printed value, so the legend shows units such as Mbit/s or kbit/s.

Building a monitoring tool

A monitoring tool built directly on RRDtool combines the commands above into three parts: a script, run on a schedule, that creates a database for each new metric to be tracked; a script, run on the same schedule as the database step, that polls each device and calls rrdtool update; and a script, run on a schedule or on request, that calls rrdtool graph and writes the resulting image to a location served by a web server. A page displaying the generated images, with a periodic page refresh or an equivalent script, completes the setup.

Other commands

  • rrdtool fetch file.rrd AVERAGE --start -1h - prints consolidated values for a time range.
  • rrdtool info file.rrd - prints the data sources and RRAs a file was created with.
  • rrdtool last file.rrd - prints the timestamp of the most recent update.
  • rrdtool dump file.rrd > file.xml and rrdtool restore file.xml file.rrd - export to and import from an XML representation, used for backups and migration between versions.
  • rrdtool tune - changes a data source's heartbeat, minimum, maximum, or type on an existing file.

Cacti, Munin, Smokeping, and collectd (with its RRD output plugin) implement the same poll-store-graph sequence described above, with a web interface, device templates, and in some cases alerting, in place of custom scripts.