1#!/usr/local/bin/perl -w 2 3# libstatgrab 4# https://libstatgrab.org 5# Copyright (C) 2003-2004 Peter Saunders 6# Copyright (C) 2003-2019 Tim Bishop 7# Copyright (C) 2003-2013 Adam Sampson 8# Copyright (C) 2012-2019 Jens Rehsack 9# 10# This program is free software; you can redistribute it and/or 11# modify it under the terms of the GNU General Public License 12# as published by the Free Software Foundation; either version 2 13# of the License, or (at your option) any later version. 14# 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License 21# along with this program; if not, write to the Free Software 22# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 23# 02110-1301, USA. 24 25use strict; 26use Getopt::Long; 27 28my $progname = "statgrab-make-mrtg-config"; 29my $statgrab = "statgrab"; 30my $workdir = undef; 31 32my $kib = 1024; 33my $mib = $kib * $kib; 34 35# Type 0 is plain integers. 36my $KIBIBYTES = 1; 37my $PERCENT = 2; 38my $FLOAT = 3; 39 40# Print an entry in the MRTG config file. 41sub entry ($$$$$$$$$$) { 42 my ($title, $vali, $valo, $max, $ylegend, $yunit, $legendi, $legendo, $gauge, $type) = @_; 43 my $name = $vali; 44 my $options = ""; 45 $options .= " noo" unless defined $valo; 46 $options .= " gauge" if $gauge; 47 my $sgoptions = ""; 48 $sgoptions .= " -o -p" if $type == $PERCENT; 49 $sgoptions .= " -f 1000" if $type == $FLOAT; 50 51 print "\n"; 52 print "Title[$name]: $title\n"; 53 print "PageTop[$name]: $title\n"; 54 print "MaxBytes[$name]: $max\n"; 55 print "YLegend[$name]: $ylegend\n"; 56 print "ShortLegend[$name]: $yunit\n"; 57 print "LegendI[$name]: $legendi\n"; 58 print "LegendO[$name]: $legendo\n" if defined $valo; 59 if ($type == $KIBIBYTES) { 60 print "kMG[$name]: Ki,Mi,Gi,Ti\n"; 61 $sgoptions .= " -K"; 62 } 63 $valo = "const.0" unless defined $valo; 64 print "Options[$name]:$options\n" if $options ne ""; 65 print "Target[$name]: `$statgrab$sgoptions -m $vali $valo`\n"; 66} 67 68my $package_version = '@PACKAGE_VERSION@'; 69my $package_bugreport = '@PACKAGE_BUGREPORT@'; 70my $help_text = <<EOF; 71Usage: $progname [OPTION]... 72Generate MRTG configuration from statgrab output and write it to stdout. 73 74--no-header Don't print MRTG global options; useful if you 75 want to include the output of this script in 76 another MRTG config file 77--workdir PATH Use PATH for MRTG's WorkDir option 78--statgrab PATH Specify location of statgrab binary 79 (default "statgrab") 80--help Display this help and exit 81 82Version $package_version - report bugs to $package_bugreport. 83EOF 84 85sub fatal ($) { 86 my ($message) = @_; 87 die "$progname: $message\n"; 88} 89 90sub main () { 91 GetOptions('statgrab=s' => \$statgrab, 92 'workdir=s' => \$workdir, 93 'no-header' => \my $no_header, 94 'help' => \my $help) or die $help_text; 95 if ($help) { 96 print "$help_text"; 97 exit 0; 98 } 99 100 unless ($no_header or defined $workdir) { 101 fatal "must specify --workdir or --no-header" 102 } 103 104 my %stats = (); 105 my %toplevel = (); 106 my %disks = (); 107 my %fss = (); 108 my %nets = (); 109 open STATGRAB, "$statgrab|" or fatal "can't run statgrab"; 110 while (<STATGRAB>) { 111 chomp; 112 /^([^=]*) = (.*)$/ or fatal "bad line in statgrab output"; 113 $stats{$1} = $2; 114 115 my @parts = split /\./, $1; 116 $toplevel{$parts[0]} = 1; 117 $disks{$parts[1]} = 1 if $parts[0] eq "disk"; 118 $fss{$parts[1]} = 1 if $parts[0] eq "fs"; 119 $nets{$parts[1]} = 1 if $parts[0] eq "net"; 120 } 121 close STATGRAB; 122 123 unless ($no_header) { 124 print "WorkDir: $workdir\n"; 125 print "Options[^]: growright\n"; 126 print "WriteExpires: Yes\n"; 127 } 128 129 if (exists $toplevel{"cpu"}) { 130 entry("CPU idle", "cpu.idle", undef, "100", "Idle", "%", "idle", undef, 1, $PERCENT); 131 entry("CPU iowait", "cpu.iowait", undef, "100", "iowait", "%", "iowait", undef, 1, $PERCENT); 132 entry("CPU kernel", "cpu.kernel", undef, "100", "Kernel", "%", "kernel", undef, 1, $PERCENT); 133 entry("CPU nice", "cpu.nice", undef, "100", "Nice", "%", "nice", undef, 1, $PERCENT); 134 entry("CPU swap", "cpu.swap", undef, "100", "Swap", "%", "swap", undef, 1, $PERCENT); 135 entry("CPU user", "cpu.user", undef, "100", "User", "%", "user", undef, 1, $PERCENT); 136 } 137 138 foreach my $disk (sort keys %disks) { 139 my $name = $stats{"disk.$disk.disk_name"}; 140 entry("Disk $name IO", "disk.$disk.read_bytes", "disk.$disk.write_bytes", 100*$mib, "IO rate", "KiB/s", "read", "write", 0, $KIBIBYTES); 141 } 142 143 foreach my $fs (sort keys %fss) { 144 my $name = $stats{"fs.$fs.mnt_point"}; 145 my $size = $stats{"fs.$fs.size"}; 146 my $inodes = $stats{"fs.$fs.total_inodes"}; 147 entry("Filesystem $name space usage", "fs.$fs.used", undef, $size, "Space used", "KiB", "used", undef, 1, $KIBIBYTES); 148 entry("Filesystem $name inode usage", "fs.$fs.used_inodes", undef, $inodes, "Inodes used", "inodes", "used", undef, 1, 0); 149 } 150 151 if (exists $toplevel{"load"}) { 152 entry("Load average over 1 minute", "load.min1", undef, 100, "Load average", "running * 1000", "load", undef, 1, $FLOAT); 153 entry("Load average over 5 minutes", "load.min5", undef, 100, "Load average", "running * 1000", "load", undef, 1, $FLOAT); 154 entry("Load average over 15 minutes", "load.min15", undef, 100, "Load average", "running * 1000", "load", undef, 1, $FLOAT); 155 } 156 157 if (exists $toplevel{"mem"}) { 158 my $total = $stats{"mem.total"}; 159 entry("Memory usage", "mem.used", "mem.cache", $total, "Memory usage", "KiB", "total", "cache", 1, $KIBIBYTES); 160 } 161 162 foreach my $net (sort keys %nets) { 163 my $name = $stats{"net.$net.interface_name"}; 164 my $speed = int($stats{"net.$net.speed"}); 165 $speed = 100 if $speed == 0; 166 167 # The speed is reported in Mbit/s; we want KiB/s. 168 $speed = int(($speed * 1000000) / (8 * $kib)); 169 170 entry("Network interface $name IO", "net.$net.rx", "net.$net.tx", $speed, "Network IO", "KiB/s", "rx", "tx", 0, $KIBIBYTES); 171 } 172 173 if (exists $toplevel{"page"}) { 174 # FIXME what's a sensible maximum? 175 entry("Paging IO", "page.in", "page.out", 1000, "Paging IO", "pages", "in", "out", 0, 0); 176 } 177 178 if (exists $toplevel{"proc"}) { 179 # FIXME mildly silly assumption 180 my $maxproc = 65536; 181 entry("Processes running", "proc.running", undef, $maxproc, "Running", "procs", "running", undef, 1, 0); 182 entry("Processes sleeping", "proc.sleeping", undef, $maxproc, "Sleeping", "procs", "running", undef, 1, 0); 183 entry("Processes stopped", "proc.stopped", undef, $maxproc, "Stopped", "procs", "running", undef, 1, 0); 184 entry("Processes", "proc.total", undef, $maxproc, "Total", "procs", "running", undef, 1, 0); 185 entry("Processes zombie", "proc.zombie", undef, $maxproc, "Zombie", "procs", "running", undef, 1, 0); 186 } 187 188 if (exists $toplevel{"swap"}) { 189 my $swapsize = $stats{"swap.total"}; 190 if ($swapsize ne "0") { 191 entry("Swap usage", "swap.used", undef, $swapsize, "Swap usage", "KiB", "used", undef, 1, $KIBIBYTES); 192 } 193 } 194 195 if (exists $toplevel{"user"}) { 196 entry("Users", "user.num", undef, 1000, "Users", "users", "users", undef, 1, 0); 197 } 198} 199 200main(); 201