I hide no shame in the fact that this is one of my first perl scripts and my very first time using rrdtool , but it seems to work just fine.
With the current rrd scripts I had to add drive info to the script, which I fear will make upgrading harder to I have opted to use a settings file.
you will need to add it to the current cron job and add the graphs to your html pages as well ( I'm working on a new php one that just adds the avable graphs)
I hope this works for you.
/etc/rddsettings.cfg
Code:
DISKDEV=sda1:
DISKDEV=sda2:tv
DISKDEV=sdb1:video
DISKDEV=hdg1:video2
DISKDEV=hdh1:video3
/usr/local/bin/rrd_diskusage.plCode:
#!/usr/bin/perl
# rrd_diskusage.pl devicename1 [devicename2 ....] partition usage
# or
# rrd_diskusage.pl <without parameters>
# in this case we get the devicenames from
# /etc/rddsettings.cfg
#
#
# extended devicename format:
#
# <device>:<mountpoint or other useful name>
#
#
# example: (without extended devicename format)
# rrd_diskusage.pl hda1 hda3 hda4
#
#
# example: (with extended devicename format)
# rrd_diskusage.pl hda1:/ hda3:/usr hda4:blablub
#
#use strict;
use RRDs;
# define location of rrdtool databases
my $rrd = '/var/lib/rrd';
my $rrdlog = '/var/lib/rrd';
# define location of images
my $graphs = '/var/www/rrdtool';
my $rrdDatabaseName = '';
my $rrdMyDatabasePath = '/var/lib/rrd';
#
my $rrdDatabasePath;
#print STDERR "$rrdDatabasePath";
#
my @rrdDevs;
if ((scalar @ARGV) > 0) {
@rrdDevs = @ARGV;
} else {
# open input file
open(inFH, "< /etc/rddsettings.cfg") or usage();
while (defined (my $inLine = <inFH>)) {
#print STDERR "$inLine";
if ($inLine =~/^DISKDEV=/o) {
(my $devname = $inLine) =~ s/^DISKDEV=//og;
chomp $devname;
push(@rrdDevs, $devname);
}
}
close(inFH);
}
#extract names
# to avoid a lot of emails from cron when not configured
if (exists $ENV{'RRD_SILENT'}) {
exit 0 if ((scalar @rrdDevs) == 0);
} else {
usage() if ((scalar @rrdDevs) == 0);
}
#..............................................................................
# fill the databases
fill_rrd ();
#..............................................................................
sub create_rrd($) {
my $rrdFile = $_[0];
#print STDERR "create: $rrdFile\n";
# awaiting an update every 300 secs
my $rrdStep = 300;
# data source = ...GAUGE, max 600 sec wait before UNKNOWN,
# no min, no max
# 0.5:1: average value calc. with 1 entry = 300sec
# 0.5:5: average value calc. with 5 entries = 5*300sec
# h36 = 3600*36 => 129600sec/300 => 432
# d7a2 = 3600*24*7 => 604800sec/300 /2 => 1008; 10min average
# d30a6 = 3600*24*30 => 2592000sec/300 /6 => 1440; 30min average
# d365a12= 3600*24*365 => 31536000sec/300 /12=> 8760; 1h average
# d7a6 = 3600*24*7 => 604800sec/300 /6 => 336; 30min max
# d30a12 = 3600*24*30 => 2592000sec/300 /12 => 720; 1h max
# d365a24= 3600*24*365 => 31536000sec/300 /24=> 4380; 2h max
RRDs::create("$rrdFile",
'--step', $rrdStep,
'DS:used:GAUGE:' .($rrdStep*2).':0:U',
'DS:avail:GAUGE:' .($rrdStep*2).':0:U',
'RRA:AVERAGE:0.5:1:432',
'RRA:AVERAGE:0.5:2:1008',
'RRA:AVERAGE:0.5:6:1440',
'RRA:AVERAGE:0.5:12:8760',
'RRA:MAX:0.5:6:336',
'RRA:MAX:0.5:12:720',
'RRA:MAX:0.5:24:4380'
);
my $ERR = RRDs::error;
die "ERROR while creating $rrdFile: $ERR\n" if $ERR;
}
#..............................................................................
sub update_rrd ($$$$$){
my $rrdFile = $_[0];
#my $dataTime = $_[1];
#my $used = $_[2];
#my $avail = $_[3];
my $device = $_[4];
# print STDERR "update: $rrdFile, dataTime=$_[1], used=$_[2], avail=$_[3]\n";
updategraph ('day',$rrdFile,$device);
updategraph ('week',$rrdFile,$device);
updategraph ('month',$rrdFile,$device);
updategraph ('year',$rrdFile,$device);
RRDs::update("$rrdFile", $_[1].':'.$_[2].':'.$_[3]);
my $ERR = RRDs::error;
die "ERROR while updating $rrdFile: $ERR\n" if $ERR;
}
sub fill_rrd () {
#print STDERR @rrdDevs;
# extract the data from df
my $rrdTime = time;
my @dfLines = `df`;
# print STDERR @dfLines;
foreach my $dfLine (@dfLines) {
chomp $dfLine;
foreach my $rrdDev (@rrdDevs) {
my $realDev;
my $extDev ='';
if ($rrdDev =~ /^(.+)\:(.+)/) {
$realDev = $1;
$extDev = '.'. $2;
$extDev =~ s:/:\,:og;
} else {
$realDev = $rrdDev;
}
my $rrdFile = "$rrdMyDatabasePath" . "/usage_" . $realDev . "." . "rrd";
my $device = $realDev ;
# print STDERR $realDev . " - " . $extDev . "\n";
# print STDERR "[$dfLine]\n";
if ($dfLine =~ /$realDev\s+\d+\s+(\d+)+\s+(\d+)/g ) {
my $usedM = sprintf("%d",$1/1024);
#print STDERR "$1 / 1024 = $usedM\n";
my $availM = sprintf("%d",$2/1024);
#print STDERR "$2 / 1024 = $availM\n";
# fill database
create_rrd($rrdFile) if not -w $rrdFile;
update_rrd($rrdFile,
$rrdTime,
$usedM,
$availM,
$device) if -w $rrdFile;
}
}
}
}
#..............................................................................
#..............................................................................
sub updategraph {
my $period = $_[0];
my $rrdfile = $_[1];
my $realDev = $_[2];
RRDs::graph ("$graphs/usage-$realDev-$period.png",
"--start", "-1$period", "-aPNG", "-i", "-z",
"--alt-y-grid", "-w 600", "-h 100", "-l 0", "-u 100", "-r",
"--color", "SHADEA#EAE9EE",
"--color", "SHADEB#EAE9EE",
"--color", "BACK#EAE9EE",
"--vertical-label", "partition used (%)",
"-t $realDev disk usage per $period",
"-b", 1024,
"DEF:used=$rrdfile:used:AVERAGE",
"DEF:avail=$rrdfile:avail:AVERAGE",
"CDEF:total=used,avail,+",
"CDEF:usedpct=100,used,total,/,*",
"CDEF:availpct=100,avail,total,/,*",
"AREA:usedpct#0000FF:used disk",
"STACK:availpct#00FF00:free disk\\j",
"GPRINT:avail:LAST:free disk\\:%9.1lf MB",
"GPRINT:used:LAST:used disk\\:%9.1lf MB",
"GPRINT:total:LAST:total disk\\:%9.1lf MB\\j",
"GPRINT:usedpct:MAX:maximal used disk\\:%3.2lf%%",
"GPRINT:usedpct:AVERAGE:average used disk\\:%3.2lf%%",
"GPRINT:usedpct:LAST:current used disk\\:%3.2lf%%\\j",
"GPRINT:availpct:MAX:maximal free disk\\:%3.2lf%%",
"GPRINT:availpct:AVERAGE:average free disk\\:%3.2lf%%",
"GPRINT:availpct:LAST:current free disk\\:%3.2lf%%\\j");
$ERROR = RRDs::error;
print "Error in RRD::graph for disk: $ERROR\n" if $ERROR;
}