{
    "mode": "man",
    "parameter": "rrd-beginners",
    "section": "1",
    "url": "https://www.chedong.com/phpMan.php/man/rrd-beginners/1/json",
    "generated": "2026-06-11T04:51:38Z",
    "synopsis": "Helping new RRDtool users to understand the basics of RRDtool",
    "sections": {
        "NAME": {
            "content": "rrd-beginners - RRDtool Beginners' Guide\n",
            "subsections": []
        },
        "SYNOPSIS": {
            "content": "Helping new RRDtool users to understand the basics of RRDtool\n",
            "subsections": []
        },
        "DESCRIPTION": {
            "content": "This manual is an attempt to assist beginners in understanding the concepts of RRDtool. It\nsheds a light on differences between RRDtool and other databases. With help of an example, it\nexplains the structure of RRDtool database. This is followed by an overview of the \"graph\"\nfeature of RRDtool.  At the end, it has sample scripts that illustrate the usage/wrapping of\nRRDtool within Shell or Perl scripts.\n",
            "subsections": [
                {
                    "name": "What makes RRDtool so special?",
                    "content": "RRDtool is GNU licensed software developed by Tobias Oetiker, a system manager at the Swiss\nFederal Institute of Technology. Though it is a database, there are distinct differences\nbetween RRDtool databases and other databases as listed below:\n\n•   RRDtool stores data; that makes it a back-end tool. The RRDtool command set allows one to\ncreate graphs; that makes it a front-end tool as well. Other databases just store data\nand can not create graphs.\n\n•   In case of linear databases, new data gets appended at the bottom of the database table.\nThus its size keeps on increasing, whereas the size of an RRDtool database is determined\nat creation time. Imagine an RRDtool database as the perimeter of a circle. Data is added\nalong the perimeter. When new data reaches the starting point, it overwrites existing\ndata. This way, the size of an RRDtool database always remains constant. The name \"Round\nRobin\" stems from this behavior.\n\n•   Other databases store the values as supplied. RRDtool can be configured to calculate the\nrate of change from the previous to the current value and store this information instead.\n\n•   Other databases get updated when values are supplied. The RRDtool database is structured\nin such a way that it needs data at predefined time intervals. If it does not get a new\nvalue during the interval, it stores an UNKNOWN value for that interval. So, when using\nthe RRDtool database, it is imperative to use scripts that run at regular intervals to\nensure a constant data flow to update the RRDtool database.\n\nRRDtool is designed to store time series of data. With every data update, an associated time\nstamp is stored. Time is always expressed in seconds passed since epoch (01-01-1970). RRDtool\ncan be installed on Unix as well as Windows. It comes with a command set to carry out various\noperations on RRD databases. This command set can be accessed from the command line, as well\nas from Shell or Perl scripts. The scripts act as wrappers for accessing data stored in\nRRDtool databases.\n"
                },
                {
                    "name": "Understanding by an example",
                    "content": "The structure of an RRD database is different than other linear databases.  Other databases\ndefine tables with columns, and many other parameters. These definitions sometimes are very\ncomplex, especially in large databases.  RRDtool databases are primarily used for monitoring\npurposes and hence are very simple in structure. The parameters that need to be defined are\nvariables that hold values and archives of those values. Being time sensitive, a couple of\ntime related parameters are also defined. Because of its structure, the definition of an\nRRDtool database also includes a provision to specify specific actions to take in the absence\nof update values. Data Source (DS), heartbeat, Date Source Type (DST), Round Robin Archive\n(RRA), and Consolidation Function (CF) are some of the terminologies related to RRDtool\ndatabases.\n\nThe structure of a database and the terminology associated with it can be best explained with\nan example.\n\nrrdtool create target.rrd \\\n--start 1023654125 \\\n--step 300 \\\nDS:mem:GAUGE:600:0:671744 \\\nRRA:AVERAGE:0.5:12:24 \\\nRRA:AVERAGE:0.5:288:31\n\nThis example creates a database named target.rrd. Start time (1'023'654'125) is specified in\ntotal number of seconds since epoch (time in seconds since 01-01-1970). While updating the\ndatabase, the update time is also specified.  This update time MUST be larger (later) than\nstart time and MUST be in seconds since epoch.\n\nThe step of 300 seconds indicates that the database expects new values every 300 seconds. The\nwrapper script should be scheduled to run every step seconds so that it updates the database\nevery step seconds.\n\nDS (Data Source) is the actual variable which relates to the parameter on the device that is\nmonitored. Its syntax is\n\nDS:variablename:DST:heartbeat:min:max\n\nDS is a key word. \"variablename\" is a name under which the parameter is saved in the\ndatabase. There can be as many DSs in a database as needed. After every step interval, a new\nvalue of DS is supplied to update the database.  This value is also called Primary Data Point\n(PDP). In our example mentioned above, a new PDP is generated every 300 seconds.\n\nNote, that if you do NOT supply new data points exactly every 300 seconds, this is not a\nproblem, RRDtool will interpolate the data accordingly.\n\nDST (Data Source Type) defines the type of the DS. It can be COUNTER, DERIVE, ABSOLUTE,\nGAUGE. A DS declared as COUNTER will save the rate of change of the value over a step period.\nThis assumes that the value is always increasing (the difference between the current and the\nprevious value is greater than 0). Traffic counters on a router are an ideal candidate for\nusing COUNTER as DST. DERIVE is the same as COUNTER, but it allows negative values as well.\nIf you want to see the rate of change in free disk space on your server, then you might want\nto use the DERIVE data type. ABSOLUTE also saves the rate of change, but it assumes that the\nprevious value is set to 0. The difference between the current and the previous value is\nalways equal to the current value. Thus it just stores the current value divided by the step\ninterval (300 seconds in our example). GAUGE does not save the rate of change. It saves the\nactual value itself. There are no divisions or calculations. Memory consumption in a server\nis a typical example of gauge. The difference between the different types DSTs can be\nexplained better with the following example:\n\nValues       = 300, 600, 900, 1200\nStep         = 300 seconds\nCOUNTER DS   =    1,  1,   1,    1\nDERIVE DS    =    1,  1,   1,    1\nABSOLUTE DS  =    1,  2,   3,    4\nGAUGE DS     = 300, 600, 900, 1200\n\nThe next parameter is heartbeat. In our example, heartbeat is 600 seconds. If the database\ndoes not get a new PDP within 300 seconds, it will wait for another 300 seconds (total 600\nseconds).  If it doesn't receive any PDP within 600 seconds, it will save an UNKNOWN value\ninto the database. This UNKNOWN value is a special feature of RRDtool - it is much better\nthan to assume a missing value was 0 (zero) or any other number which might also be a valid\ndata value.  For example, the traffic flow counter on a router keeps increasing. Lets say, a\nvalue is missed for an interval and 0 is stored instead of UNKNOWN. Now when the next value\nbecomes available, it will calculate the difference between the current value and the\nprevious value (0) which is not correct. So, inserting the value UNKNOWN makes much more\nsense here.\n\nThe next two parameters are the minimum and maximum value, respectively. If the variable to\nbe stored has predictable maximum and minimum values, this should be specified here. Any\nupdate value falling out of this range will be stored as UNKNOWN.\n\nThe next line declares a round robin archive (RRA). The syntax for declaring an RRA is\n\nRRA:CF:xff:step:rows\n\nRRA is the keyword to declare RRAs. The consolidation function (CF) can be AVERAGE, MINIMUM,\nMAXIMUM, and LAST. The concept of the consolidated data point (CDP) comes into the picture\nhere. A CDP is CFed (averaged, maximum/minimum value or last value) from step number of PDPs.\nThis RRA will hold rows CDPs.\n\nLets have a look at the example above. For the first RRA, 12 (steps) PDPs (DS variables) are\nAVERAGEed (CF) to form one CDP. 24 (rows) of theses CDPs are archived. Each PDP occurs at 300\nseconds. 12 PDPs represent 12 times 300 seconds which is 1 hour. It means 1 CDP (which is\nequal to 12 PDPs) represents data worth 1 hour. 24 such CDPs represent 1 day (1 hour times 24\nCDPs). This means, this RRA is an archive for one day. After 24 CDPs, CDP number 25 will\nreplace the 1st CDP. The second RRA saves 31 CDPs; each CPD represents an AVERAGE value for a\nday (288 PDPs, each covering 300 seconds = 24 hours). Therefore this RRA is an archive for\none month. A single database can have many RRAs. If there are multiple DSs, each individual\nRRA will save data for all the DSs in the database. For example, if a database has 3 DSs and\ndaily, weekly, monthly, and yearly RRAs are declared, then each RRA will hold data from all 3\ndata sources.\n"
                },
                {
                    "name": "Graphical Magic",
                    "content": "Another important feature of RRDtool is its ability to create graphs. The \"graph\" command\nuses the \"fetch\" command internally to retrieve values from the database. With the retrieved\nvalues it draws graphs as defined by the parameters supplied on the command line. A single\ngraph can show different DS (Data Sources) from a database. It is also possible to show the\nvalues from more than one database in a single graph. Often, it is necessary to perform some\nmath on the values retrieved from the database before plotting them. For example, in SNMP\nreplies, memory consumption values are usually specified in KBytes and traffic flow on\ninterfaces is specified in Bytes. Graphs for these values will be more meaningful if values\nare represented in MBytes and mbps. The RRDtool graph command allows one to define such\nconversions. Apart from mathematical calculations, it is also possible to perform logical\noperations such as greater than, less than, and if/then/else. If a database contains more\nthan one RRA archive, then a question may arise - how does RRDtool decide which RRA archive\nto use for retrieving the values? RRDtool looks at several things when making its choice.\nFirst it makes sure that the RRA covers as much of the graphing time frame as possible.\nSecond it looks at the resolution of the RRA compared to the resolution of the graph. It\ntries to find one which has the same or higher better resolution. With the \"-r\" option you\ncan force RRDtool to assume a different resolution than the one calculated from the pixel\nwidth of the graph.\n\nValues of different variables can be presented in 5 different shapes in a graph - AREA,\nLINE1, LINE2, LINE3, and STACK. AREA is represented by a solid colored area with values as\nthe boundary of this area. LINE1/2/3 (increasing width) are just plain lines representing the\nvalues. STACK is also an area but it is \"stack\"ed on top AREA or LINE1/2/3. Another important\nthing to note is that variables are plotted in the order they are defined in the graph\ncommand. Therefore care must be taken to define STACK only after defining AREA/LINE. It is\nalso possible to put formatted comments within the graph.  Detailed instructions can be found\nin the graph manual.\n"
                },
                {
                    "name": "Wrapping RRDtool within Shell/Perl script",
                    "content": "After understanding RRDtool it is now a time to actually use RRDtool in scripts. Tasks\ninvolved in network management are data collection, data storage, and data retrieval. In the\nfollowing example, the previously created target.rrd database is used. Data collection and\ndata storage is done using Shell scripts. Data retrieval and report generation is done using\nPerl scripts. These scripts are shown below:\n\nShell script (collects data, updates database)\n\n#!/bin/sh\na=0\nwhile [ \"$a\" == 0 ]; do\nsnmpwalk -c public 192.168.1.250 hrSWRunPerfMem > snmpreply\ntotalmem=`awk 'BEGIN {totmem=0}\n{ if ($NF == \"KBytes\")\n{totmem=totmem+$(NF-1)}\n}\nEND {print totmem}' snmpreply`\n# I can use N as a replacement for the current time\nrrdtool update target.rrd N:$totalmem\n# sleep until the next 300 seconds are full\nperl -e 'sleep 300 - time % 300'\ndone # end of while loop\n\nPerl script (retrieves data from database and generates graphs and statistics)\n\n#!/usr/bin/perl -w\n# This script fetches data from target.rrd, creates a graph of memory\n# consumption on the target (Dual P3 Processor 1 GHz, 656 MB RAM)\n\n# call the RRD perl module\nuse lib qw( /usr/local/rrdtool-1.0.41/lib/perl ../lib/perl );\nuse RRDs;\nmy $curtime = time();                # set current time\nmy $endtime = $curtime - 86400;     # set end time to 24 hours ago\nmy $starttime = $endtime - 2592000; # set start 30 days in the past\n\n# fetch average values from the RRD database between start and end time\nmy ($start,$step,$dsnames,$data) =\nRRDs::fetch(\"target.rrd\", \"AVERAGE\",\n\"-r\", \"600\", \"-s\", \"$starttime\", \"-e\", \"$endtime\");\n# save fetched values in a 2-dimensional array\nmy $rows = 0;\nmy $columns = 0;\nmy $timevariable = $start;\nforeach $line (@$data) {\n$vals[$rows][$columns] = $timevariable;\n$timevariable = $timevariable + $step;\nforeach $val (@$line) {\n$vals[$rows][++$columns] = $val;}\n$rows++;\n$columns = 0;\n}\nmy $tottime = 0;\nmy $count = 0;\n# save the values from the 2-dimensional into a 1-dimensional array\nfor $i ( 0 .. $#vals ) {\n$totmem[$count] = $vals[$i][1];\n$count++;\n}\nmy $totmemsum = 0;\n# calculate the total of all values\nfor $i ( 0 .. ($count-1) ) {\n$totmemsum = $totmemsum + $totmem[$i];\n}\n# calculate the average of the array\nmy $totmemave = $totmemsum/($count);\n# create the graph\nRRDs::graph (\"/images/mem$count.png\",\n\"--title= Memory Usage\",\n\"--vertical-label=Memory Consumption (MB)\",\n\"--start=$starttime\",\n\"--end=$endtime\",\n\"--color=BACK#CCCCCC\",\n\"--color=CANVAS#CCFFFF\",\n\"--color=SHADEB#9999CC\",\n\"--height=125\",\n\"--upper-limit=656\",\n\"--lower-limit=0\",\n\"--rigid\",\n\"--base=1024\",\n\"DEF:totmem=target.rrd:mem:AVERAGE\",\n\"CDEF:totmemcor=totmem,0,671744,LIMIT,UN,0,totmem,IF,1024,/\",\n\"CDEF:machinemem=totmem,656,+,totmem,-\",\n\"COMMENT:Memory Consumption between $starttime\",\n\"COMMENT:    and $endtime                     \",\n\"HRULE:656#000000:Maximum Available Memory - 656 MB\",\n\"AREA:machinemem#CCFFFF:Memory Unused\",\n\"AREA:totmemcor#6699CC:Total memory consumed in MB\");\nmy $err=RRDs::error;\nif ($err) {print \"problem generating the graph: $err\\n\";}\n# print the output\nprint \"Average memory consumption is \";\nprintf \"%5.2f\",$totmemave/1024;\nprint \" MB. Graphical representation can be found at /images/mem$count.png.\";\n"
                }
            ]
        },
        "AUTHOR": {
            "content": "Ketan Patel <k2pattu@yahoo.com>\n\n\n\n1.7.2                                        2022-03-17                             RRD-BEGINNERS(1)",
            "subsections": []
        }
    },
    "summary": "rrd-beginners - RRDtool Beginners' Guide",
    "flags": [],
    "examples": [],
    "see_also": []
}