You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by do...@apache.org on 2006/09/26 06:24:20 UTC

svn commit: r449895 - /spamassassin/branches/3.1/contrib/check_spamd

Author: dos
Date: Mon Sep 25 21:24:20 2006
New Revision: 449895

URL: http://svn.apache.org/viewvc?view=rev&rev=449895
Log:
add my nagios plugin for monitoring spamd to contrib/

Added:
    spamassassin/branches/3.1/contrib/check_spamd   (with props)

Added: spamassassin/branches/3.1/contrib/check_spamd
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.1/contrib/check_spamd?view=auto&rev=449895
==============================================================================
--- spamassassin/branches/3.1/contrib/check_spamd (added)
+++ spamassassin/branches/3.1/contrib/check_spamd Mon Sep 25 21:24:20 2006
@@ -0,0 +1,424 @@
+#!/usr/bin/perl -w -T
+
+########################################################################
+#
+# <@LICENSE>
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# </...@LICENSE>
+#
+########################################################################
+
+# Written by Daryl C. W. O'Shea, DOS Technologies <sp...@dostech.ca>
+# See  perldoc check_spamd  for program info.
+
+use strict;
+
+use Getopt::Long;
+
+use constant HAS_TIME_HIRES => eval { require Time::HiRes; };
+use constant HAS_MSA_CLIENT => eval { require Mail::SpamAssassin::Client; };
+use constant HAS_MSA_TIMEOUT => eval { require Mail::SpamAssassin::Timeout; };
+
+### nagios plugin return codes: 0 OK / 1 Warning / 2 Critical / 3 Unknown ###
+use constant EX_OK	 => 0;
+use constant EX_WARNING	 => 1;
+use constant EX_CRITICAL => 2;
+use constant EX_UNKNOWN	 => 3;
+
+my $VERSION = "0.01";
+
+my %status_text = (
+  '0'	=> 'OK',
+  '1'	=> 'WARNING',
+  '2'	=> 'CRITICAL',
+  '3'	=> 'UNKNOWN',
+);
+
+my %opt = (
+  'critical'	=> undef,
+  'hostname'	=> undef,
+  'port'	=> undef,
+  'socketpath'	=> undef,
+  'timeout'	=> 45,
+  'verbose'	=> undef,
+  'warning'	=> undef,
+);
+
+# Parse the command line
+Getopt::Long::Configure("bundling");
+GetOptions(
+  'critical|c=s'	=> \$opt{'critical'},
+  'help|h|?'		=> sub { print_usage_and_exit(); },
+  'hostname|H=s'	=> \$opt{'hostname'},
+  'port|p=s'		=> \$opt{'port'},
+  'socketpath=s'	=> \$opt{'socketpath'},
+  'timeout|t=s'		=> \$opt{'timeout'},
+  'verbose|v'		=> \$opt{'verbose'},
+  'version|V'		=> sub { print "check_spamd version $VERSION\n"; exit EX_UNKNOWN; },
+  'warning|w=s'		=> \$opt{'warning'},
+
+) or print_usage_and_exit();
+
+
+if (defined $opt{'critical'}) {
+  if ($opt{'critical'} =~ /^(\d+(?:\.\d*)?)$/) {
+    $opt{'critical'} = $1;
+  } else {
+    print "SPAMD UNKNOWN: invalid critical config value provided\n";
+    exit EX_UNKNOWN;
+  }
+}
+
+if (defined $opt{'hostname'}) {
+  if ($opt{'hostname'} =~ /^([A-Za-z0-9_.-]+)$/) {
+    $opt{'hostname'} = $1;
+  } else {
+    print "SPAMD UNKNOWN: invalid hostname config value provided\n";
+    exit EX_UNKNOWN;
+  }
+}
+
+if (defined $opt{'port'}) {
+  if ($opt{'port'} =~ /^(\d+)$/) {
+    $opt{'port'} = $1;
+  } else {
+    print "SPAMD UNKNOWN: invalid port config value provided\n";
+    exit EX_UNKNOWN;
+  }
+}
+
+# TODO: --socketpath isn't checked, suboptimal
+
+if ($opt{'timeout'} =~ /^(\d+(?:\.\d*)?)$/ && $opt{'timeout'} >= 1) {
+  $opt{'timeout'} = $1;
+} else {
+  print "SPAMD UNKNOWN: invalid timeout config value provided\n";
+  exit EX_UNKNOWN;
+}
+
+if (defined $opt{'warning'}) {
+  if ($opt{'warning'} =~ /^(\d+(?:\.\d*)?)$/) {
+    $opt{'warning'} = $1;
+  } else {
+    print "SPAMD UNKNOWN: invalid warning config value provided\n";
+    exit EX_UNKNOWN;
+  }
+}
+
+# logic checking
+if (defined $opt{'critical'} && defined $opt{'warning'} &&
+	$opt{'critical'} < $opt{'warning'}) {
+  print "SPAMD UNKNOWN: critical value is less than warning value, config not valid\n";
+  exit EX_UNKNOWN;
+}
+
+if (defined $opt{'critical'} && defined $opt{'timeout'} &&
+	$opt{'critical'} > $opt{'timeout'}) {
+  print "SPAMD UNKNOWN: critical value is greater than timeout value, config not valid\n";
+  exit EX_UNKNOWN;
+}
+
+if (defined $opt{'warning'} && defined $opt{'timeout'} &&
+	$opt{'warning'} > $opt{'timeout'}) {
+  print "SPAMD UNKNOWN: warning value is greater than timeout value, config not valid\n";
+  exit EX_UNKNOWN;
+}
+
+# check to make sure that both TCP and UNIX domain socket info wasn't provided
+if ((defined $opt{'hostname'} || defined $opt{'port'}) && defined $opt{'socketpath'}) {
+  print "SPAMD UNKNOWN: both TCP and UNIX domain socket info provided, only one can be used\n";
+  exit EX_UNKNOWN;
+}
+
+# if not provided with a spamd service to connect to set some defaults
+unless (defined $opt{'socketpath'}) {
+  $opt{'hostname'} ||= 'localhost';
+  $opt{'port'} ||= 783;
+}
+
+
+if ($opt{'verbose'}) {
+  print ((HAS_MSA_CLIENT ? "loaded" : "failed to load") ." Mail::SpamAssassin::Client\n");
+  print ((HAS_MSA_TIMEOUT ? "loaded" : "failed to load") ." Mail::SpamAssassin::Timeout\n");
+}
+
+# If there's no client available, there's no way to check the service...
+unless (HAS_MSA_CLIENT && HAS_MSA_TIMEOUT) {
+  # Nagios will only display the first line printed.
+  print "SPAMD UNKNOWN: could not load M:SA::Client\n" unless HAS_MSA_CLIENT;
+  print "SPAMD UNKNOWN: could not load M:SA::Timeout\n" unless HAS_MSA_TIMEOUT;
+  print "cannot continue\n" if $opt{'verbose'};
+  exit EX_UNKNOWN;
+}
+
+
+# If the client connection fails it'll spit out it's own error message which
+# is probably more appropriate than anything we can provide to Nagios ourself.
+# We'll still spit out something later, but Nagios will ignore it since it
+# only uses the first line of output.
+my $client;
+if (defined $opt{'port'}) {
+ $client = new Mail::SpamAssassin::Client({port => $opt{'port'},
+					   host => $opt{'hostname'}});
+} else {
+ $client = new Mail::SpamAssassin::Client({socketpath => $opt{'socketpath'}});
+}
+
+# this'd be weird, but totally dependent on the client
+unless (defined $client) {
+  print "SPAMD UNKNOWN: could not create M::SA::Client instance\n";
+  print "failed to create Mail::SpamAssassin::Client instance\n" if $opt{'verbose'};
+  exit EX_UNKNOWN;
+}
+
+# until we try a ping, the ping response status is unknown
+my $response = -1;
+print "connecting to spamd for ping\n" if $opt{'verbose'};
+
+my $timer = Mail::SpamAssassin::Timeout->new({ secs => $opt{'timeout'}});
+my $t0 = (HAS_TIME_HIRES ? Time::HiRes::time() : time());
+
+my $err = $timer->run(sub {
+  if ($client->ping()) {
+    $response = 1;
+  } else {
+    $response = 0;
+  }
+});
+
+my $elapsed = (HAS_TIME_HIRES ? Time::HiRes::time() : time()) - $t0;
+
+
+# a ping response should be most common, we'll handle it first
+if ($response == 1) {
+  # it's possible that we may timeout right after setting the response status to 1
+  # since the timeout value > the critical value, this is a critical state
+  if ((defined $opt{'critical'} && $elapsed > $opt{'critical'}) || $timer->timed_out()) {
+    printf("SPAMD CRITICAL: %.3f second ping response time\n", $elapsed);
+    exit EX_CRITICAL;
+  }
+
+  # warning state will never timeout since that'd be critical (above)
+  if (defined $opt{'warning'} && ($elapsed > $opt{'warning'})) {
+    printf("SPAMD WARNING: %.3f second ping response time\n", $elapsed);
+    exit EX_WARNING;
+  }
+
+  # otherwise we got a timely ping response
+  printf("SPAMD OK: %.3f second ping repsonse time\n", $elapsed);
+  exit EX_OK;
+}
+
+# any way we get a failed ping response is a critical state
+if ($response == 0) {
+  printf("SPAMD CRITICAL: ping failed in %.3f seconds\n", $elapsed);
+  exit EX_CRITICAL;
+}
+
+if ($response == -1) {
+  # this is the common timeout scenario
+  if ($timer->timed_out()) {
+    printf("SPAMD CRITICAL: ping timed out in %.3f seconds\n", $elapsed);
+    exit EX_CRITICAL;
+  }
+
+  # dos: I'll buy lunch for the first person that gets a page about this while
+  # they're sleeping if they come to Midland, ON to get it
+  printf("SPAMD UNKNOWN: assertion! unknown ping response status without timeout after %.3f seconds\n", $elapsed);
+  exit EX_UNKNOWN;
+}
+
+# and some apple pie too
+exit EX_UNKNOWN;
+
+
+#############################################################################
+
+sub print_usage_and_exit {
+  print <<EOF;
+check_spamd version $VERSION
+
+For more details, use "perldoc check_spamd".
+
+Usage:
+   check_spamd [options]
+
+    Options:
+
+     -c secs, --critical=secs          Critical ping response threshold
+     -h, -?, --help                    Print usage message
+     -H hostname, --hostname=hostname  Hostname of spamd service to ping
+     -p port, --port=port              Port of spamd service to ping
+     --socketpath=path                 Connect to given UNIX domain socket
+     -t secs, --timeout=secs           Max time to wait for a ping response
+     -v, --verbose                     Verbose debug output
+     -V, --version                     Output version info
+     -w secs, --warning=secs           Warning ping response threshold
+
+EOF
+
+  exit EX_UNKNOWN;
+}
+
+# Don't use a __DATA__ here, it screws up embedded Perl Nagios (ePN)
+
+=head1 NAME
+
+check_spamd - spamd monitoring script for use with Nagios, etc.
+
+=head1 SYNOPSIS
+
+check_spamd [options]
+
+Options:
+
+ -c secs, --critical=secs          Critical ping response threshold
+ -h, -?, --help                    Print usage message
+ -H hostname, --hostname=hostname  Hostname of spamd service to ping
+ -p port, --port=port              Port of spamd service to ping
+ --socketpath=path                 Connect to given UNIX domain socket
+ -t secs, --timeout=secs           Max time to wait for a ping response
+ -v, --verbose                     Verbose debug output
+ -V, --version                     Output version info
+ -w secs, --warning=secs           Warning ping response threshold
+
+
+=head1 DESCRIPTION
+
+The purpose of this program is to provide a tool to monitor the status of
+C<spamd> server processes.  spamd is the daemonized version of the
+spamassassin executable, both provided in the SpamAssassin distribution.
+
+This program is designed for use, as a plugin, with the Nagios service
+monitoring software available from http://nagios.org.  It might be compatible
+with other service monitoring packages.  It is also useful as a command line
+utility or as a component of a custom shell script.
+
+=head1 OPTIONS
+
+Options of the long form can be shortened as long as the remain
+unambiguous (i.e. B<--host> can be used instead of B<--hostname>).
+
+=over 4
+
+=item B<-c> I<secs>, B<--critical>=I<secs>
+
+Critical ping response threshold in seconds.  If a spamd ping response takes
+longer than the value specified (in seconds) the program will exit with a
+value of 2 to indicate the critical status.
+
+This value must be at least as long as the value specified for B<warning> and
+less than the value specified for B<timeout>.
+
+=item B<-h>, B<-?>, B<--help>
+
+Prints this usage message and exits.
+
+=item B<-H> I<hostname>, B<--hostname>=I<hostname>
+
+The hostname, or IP address, of the spamd service to ping.  By default the
+hostname B<localhost> is used.  If B<--socketpath> is set this value will be
+ignored.
+
+=item B<-p> I<port>, B<--port>=I<port>
+
+The port of the spamd service to ping.  By default port B<783> (the spamd
+default port number) is used.  If B<--socketpath> is set this value will be
+ignored.
+
+=item B<--socketpath>=I<path>
+
+Connect to given UNIX domain socket.  Use instead of a hostname and TCP port.
+When set, any hostname and TCP port specified will be ignored.
+
+=item B<-t> I<secs>, B<--timeout>=I<secs>
+
+The maximum time to wait for a ping response.  Once exceeded the program will
+exit with a value of 2 to indicate the critical status.  The default timeout
+value is 45 seconds.  The timeout must be no less than 1 second.
+
+This value must be greater than the values specified for both the B<critical>
+and B<warning> values.
+
+=item B<-v>, B<--verbose>
+
+Display verbose debug output on STDOUT.
+
+=item B<-V>, B<--version>
+
+Display version info on STDOUT.
+
+=item B<-w> I<secs>, B<--warning>=I<secs>
+
+Warning ping response threshold in seconds.  If a spamd ping response takes
+longer than the value specified (in seconds), and does not exceed the
+B<critical> threshold value, the program will exit with a value of 1 to
+indicate the warning staus.
+
+This value must be no longer than the value specified for B<critical> and
+less than the value specified for B<timeout>.
+
+=back
+
+=head1 EXIT CODES
+
+The program will indicate the status of the spamd process being monitored by
+exiting with one of these values:
+
+=over 4
+
+=item 0
+
+OK: A spamd ping response was received within all threshold times.
+
+=item 1
+
+WARNING: A spamd ping response exceeded the warning threshold but not the
+critical threshold.
+
+=item 2
+
+CRITICAL: A spamd ping response exceeded either the critical threshold or the
+timeout value.
+
+=item 3
+
+UNKNOWN: An error, probably caused by a missing dependency or an invalid
+configuration parameter being supplied, occurred in the check_spamd program.
+
+=back
+
+=head1 SEE ALSO
+
+spamc(1)
+spamd(1)
+spamassassin(1)
+
+=head1 PREREQUISITES
+
+C<Mail::SpamAssassin> version 3.1.1 or higher (3.1.6 or higher recommended)
+
+=head1 AUTHOR
+
+Daryl C. W. O'Shea, DOS Technologies <sp...@dostech.ca>
+
+=head1 LICENSE
+
+check_spamd is distributed under the Apache License, Version 2.0, as
+described in the file C<LICENSE> included with the Apache SpamAssassin
+distribution and available at http://www.apache.org/licenses/LICENSE-2.0
+
+=cut

Propchange: spamassassin/branches/3.1/contrib/check_spamd
------------------------------------------------------------------------------
    svn:executable = *