#!/usr/bin/perl -w =encoding utf8 =head1 NAME yum - Munin plugin to monitor pending update packages. It will send/show a critical warning, if security updates are pending. =head1 APPLICABLE SYSTEMS Linux distributions that use yum as software package management tool. =head1 CONFIGURATION The plugin will not show up in the Munin website per default as it contains information that is useful for any attacker. That is done by the following config directive: =over 2 # munin-run yum config B =back If you have password protected your Munin website and trust your known visitors you can make graph and more information visible by setting the following environment variables in the plugins configuration. =over 2 shownames - set to value 1, if you want to see the names of the pending packages in the field 'pending.extinfo' showgraph - set to value 'yes', if you want the plugins graph to show up in Munin website. Remove or comment the declaration of env.showgraph in plugin-conf.d if you want to hide the plugins graph again. =back B =over 2 [yum] env.showgraph yes env.shownames 0 =back =head2 SPECIAL YUM PLUGIN NEEDED Package yum-plugin-security is needed as this Munin plugin investigates how many security updates are pending. Install the package with the command: # yum install yum-plugin-security =head2 CRONJOB A cronjob has to be run outside of Munin to create and freshen up the plugins statefile with recent info from yum. Therein the plugin is called with the 'update' option. E.g. place a file with the following line in directory /etc/crond.d/: # Do not start at the same time like munin-cron, # as both will access the plugins statefile 38 */6 * * * root /usr/sbin/munin-run yum update =head1 AUTHOR Copyright 2006 Dagfinn Ilmari Mannsåker Copyright 2014 Gabriele Pohl =head1 LICENSE GPLv2 =head1 MAGIC MARKERS #%# family=manual #%# capabilities=autoconf =cut use strict; my $counter=0; my $statefile = "$ENV{MUNIN_PLUGSTATE}/yum.state"; sub update { if (-l $statefile) { die "$statefile is a symlink, not touching.\n"; } open my $state, '>', $statefile or die "Can't open $statefile for writing: $!\n"; # Get number of security updates open my $yum, '-|', 'yum -q --security list updates' or die "Can't run 'yum -q --security list updates': $!"; while (<$yum>) { next unless /^(\S+)\.\S+\s+\S+\s+\S+/; $counter++; } print $state "$counter pending security updates\n"; close $yum or die "Error running 'yum -q --security list updates': $!\n"; open $yum, '-|', 'yum -q list updates' or die "Can't run 'yum -q list updates': $!"; while (<$yum>) { next unless /^(\S+)\.\S+\s+\S+\s+\S+/; print $state "$1\n"; } close $yum or die "Error running 'yum -q list updates': $!\n"; close $state or die "Error writing $statefile: $!\n"; } sub autoconf { if (system('yum --version >/dev/null 2>/dev/null') != 0) { print "no (Could not run yum)\n"; } elsif (! -r $statefile) { print "no (Could not find statefile. Please read 'munindoc yum')\n"; } else { print "yes\n"; } exit 0; } sub config { my $showgraph = exists $ENV{'showgraph'} ? 'yes' : 'no'; print "graph_title Pending Updates\n"; print "graph_category security\n"; print "graph ", $showgraph, "\n"; print "security.label security\n"; print "security.info Number of pending security updates\n"; print "security.draw AREA\n"; print "security.colour COLOUR2\n"; print "security.critical 0\n"; print "pending.label pending\n"; print "pending.info Number of all pending updates (including security updates)\n"; print "pending.draw LINE2\n"; print "pending.warning 20\n"; } sub report { my @packages; open my $state, '<', $statefile or die "Can't open $statefile for reading: $! Please read 'munindoc yum' to understand why if the file does not exist.\n"; # read number of security updates in first line my $line = <$state>; if ($line =~ /^(\d+) pending security updates$/) { print 'security.value ', $1, "\n"; } else { die "Missing info about pending security updates in plugins statefile\n"; } chomp(@packages = <$state>); close $state; print 'pending.value ', scalar(@packages), "\n"; if (exists $ENV{'shownames'}) { print 'pending.extinfo ', join(' ', @packages), "\n" if (@packages && ($ENV{'shownames'} eq 1)); } } if ($ARGV[0]) { my $arg = $ARGV[0]; my %funcs = ( update => \&update, config => \&config, autoconf => \&autoconf, ); if (exists $funcs{$arg}) { $funcs{$arg}->(); } else { die "Unknown argument '$arg'\n"; } } else { report(); }