#!/usr/bin/perl # -*- perl -*- =head1 NAME exim_mailstats - Plugin to monitor the number of mails received and delivered by exim. =head1 APPLICABLE SYSTEMS Exim version 3 or 4. =head1 CONFIGURATION Usually no configuration is needed for this plugin. [exim*] env.logdir /path/to/exim-logs/ env.logname mainlog env.exim /usr/sbin/exim The default value for the C variable is determined by running C. C is the default name given to exims main log, but it has been known to be called "main.log" in some versions of Red Hat/Fedora for example. NOTE: If you need to set logname you must also set logdir as there is no automatic way to determine the path then. The default value of the C variable is C, but if there is a executable called C this is used instead. =head1 INTERPRETATION Need some input from an exim postmaster here. =head1 MAGIC MARKERS #%# family=auto #%# capabilities=autoconf =head1 BUGS None Known =head1 AUTHOR Copyright (C) 2002-2008 Torstein Svendsen, Jimmy Olsen, Nicolai Langfeldt Original author not documented, but likely Torstein Svendsen in 2002. Further messing by Jimmy Olsen the same year. Bugfixing and cleanup by Nicolai Langfeldt 2008. =head1 LICENSE GPLv2 =cut # In most installations the "use lib" can be removed as the Munin # modules are installed in perls module path. use strict; use lib $ENV{'MUNIN_LIBDIR'}; use Munin::Plugin; ########## sub get_exim_logfile { my ($spec, $type, $time) = @_; chomp($spec); $time = time() unless $time; my $logfile = $spec; $logfile =~ s/^log_file_path = //; $logfile =~ s/\%s/$type/; if( $logfile =~ /\%D/ ) { my @t=localtime($time); my $ts = sprintf("%04d%02d%02d",$t[5]+1900, $t[4]+1, $t[3]); $logfile =~ s/\%D/$ts/g; } my @lfiles = split(/\s?:\s?/, $logfile); foreach (@lfiles) { return $_ unless /^syslog/; } return undef; } my $pos = undef; my $received = 0; my $completed = 0; my $rejected = 0; my $dirname; ($dirname = $0) =~ s/[^\/]+$//; my $EXIM = "/usr/sbin/exim"; $EXIM = "/usr/sbin/exim4" if (-x "/usr/sbin/exim4"); # a Debianism $EXIM = $ENV{'exim'} if defined $ENV{'exim'}; my $LOGDIR = $ENV{'logdir'} || undef; my $LOGNAME = $ENV{'logname'} || ''; my $logfile; if ( $ARGV[0] and $ARGV[0] eq "autoconf" ) { my $logfile; if(defined($LOGDIR)) { if(! -d $LOGDIR) { print "no (logdir does not exist)\n"; exit 1; } $logfile = $LOGDIR . '/' . ($LOGNAME || 'mainlog'); } else { my $logfilespec = `$EXIM -bP log_file_path 2>/dev/null`; if (! $?) { $logfile = get_exim_logfile( $logfilespec, 'main'); if (! defined($logfile) ) { print "no (not able to parse output of '$EXIM -bP log_file_path' = '$logfilespec')\n"; exit 1; } } elsif ($? eq "127") { print "no (exim not found)\n"; exit 1; } else { print "no ('$EXIM -bP log_file_path' returned an error)\n"; exit 1; } } if ($logfile) { if (-r "$logfile") { print "yes\n"; exit 0; } else { print "no (logfile '$logfile' not readable)\n"; } } exit 1; } my $logfilespec; if(defined($LOGDIR)) { $logfilespec = ''; $logfile = $LOGDIR . '/' . ($LOGNAME || 'mainlog'); } else { $logfilespec = `$EXIM -bP log_file_path`; $logfile = get_exim_logfile( $logfilespec, 'main'); } exit 1 unless -r $logfile; if ( $ARGV[0] and $ARGV[0] eq "config" ) { print "graph_title Exim mail throughput\n"; print "graph_args --base 1000 -l 0\n"; print "graph_vlabel mails/\${graph_period}\n"; print "graph_scale no\n"; print "graph_category exim\n"; print "received.label received\n"; print "received.type DERIVE\n"; print "received.min 0\n"; print "received.draw AREA\n"; print "completed.label completed\n"; print "completed.type DERIVE\n"; print "completed.min 0\n"; print "rejected.label rejected\n"; print "rejected.type DERIVE\n"; print "rejected.min 0\n"; exit 0; } if (! -f $logfile) { print "completed.value U\n"; print "received.value U\n"; print "rejected.value U\n"; exit 0; } ($pos,$received,$completed,$rejected) = restore_state(); # No (valid) state present? $pos = $received = $completed = $rejected = 0 if !defined($rejected); $pos = parseEximfile ($logfile, $pos); print "received.value $received\n"; print "completed.value $completed\n"; print "rejected.value $rejected\n"; save_state($pos,$received,$completed,$rejected); sub parseEximfile { my ($fname, $start, $stop) = @_; my ($LOGFILE,$rotated) = tail_open($fname, $start); if ($rotated) { # Reset everything if the log has been rotated $pos = $received = $completed = $rejected = 0; } my $line; while ($line = <$LOGFILE>) { chomp ($line); # delete the pid out if there is one (Debian #440622) $line =~ s/^(.{19} )\[\d+\] /$1/; if (substr ($line, 37,2 ) eq '<=') { $received++; } elsif (substr ($line, 37,9) eq 'Completed') { $completed++; } elsif ($line=~/rejected/) { $rejected++; } } return tail_close($LOGFILE); } # vim:syntax=perl