PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/nrpe/files/default/plugins/Nagios/Plugin.pm

http://github.com/mdxp/cookbooks
Perl | 450 lines | 355 code | 64 blank | 31 comment | 60 complexity | 458859711c8caac6c751fdede6f5df8f MD5 | raw file
  1. #
  2. # Common stuff for Nagios plugins
  3. #
  4. package Nagios::Plugin;
  5. use strict;
  6. require Exporter;
  7. use File::Basename;
  8. use Config::Tiny;
  9. use Carp;
  10. use Getopt::Long;
  11. Getopt::Long::Configure('bundling');
  12. use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $PLUGIN $TIMEOUT $VERBOSE $VERSION);
  13. @ISA = qw(Exporter);
  14. @EXPORT = qw($PLUGIN $TIMEOUT $VERBOSE parse_args nagios_exit exit_results);
  15. @EXPORT_OK = qw(load_config);
  16. %EXPORT_TAGS = (
  17. std => [ @EXPORT ],
  18. all => [ @EXPORT, @EXPORT_OK ],
  19. );
  20. $TIMEOUT = 15;
  21. BEGIN {
  22. my ($pkg, $filename) = caller(2);
  23. # basename $0 works fine for deriving plugin name except under ePN
  24. if ($filename && $filename !~ m/EVAL/i) {
  25. $PLUGIN = basename $filename;
  26. } else {
  27. # Nasty hack - under ePN, try and derive the plugin name from the pkg name
  28. $PLUGIN = lc $pkg;
  29. $PLUGIN =~ s/^.*:://;
  30. $PLUGIN =~ s/_5F/_/gi;
  31. }
  32. }
  33. my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);
  34. # Nagios::Plugin version (not _plugin_ version)
  35. $VERSION = 0.04;
  36. # ------------------------------------------------------------------------
  37. # Private subroutines
  38. sub print_revision
  39. {
  40. my ($version) = @_;
  41. print "$PLUGIN $version";
  42. }
  43. sub print_help {
  44. my ($version, $usage, $help, $licence, $blurb, $help_extra) = @_;
  45. print_revision($version);
  46. print "$licence\n";
  47. print "$blurb\n" if $blurb;
  48. print "$usage\n";
  49. print $help;
  50. print $help_extra if $help_extra;
  51. }
  52. # ------------------------------------------------------------------------
  53. # Public subroutines
  54. # load_config('section')
  55. sub load_config {
  56. my ($section) = @_;
  57. $section ||= $PLUGIN;
  58. my $config_file = '/etc/nagios/plugins.cfg';
  59. return {} unless -f $config_file;
  60. my $ct = Config::Tiny->read($config_file);
  61. return { %{$ct->{$section} || {}} } if ref $ct;
  62. return {};
  63. }
  64. # nagios_exit("CODE", "error string")
  65. sub nagios_exit
  66. {
  67. my $code = shift;
  68. my $errstr = join ', ', @_;
  69. $code ||= "UNKNOWN";
  70. die "invalid code '$code'" unless exists $ERRORS{$code};
  71. if ($errstr && $errstr ne '1') {
  72. $errstr .= "\n" unless substr($errstr,-1) eq "\n";
  73. my $short_name = uc $PLUGIN;
  74. $short_name =~ s/^check_//i;
  75. print "$short_name $code - $errstr";
  76. }
  77. exit $ERRORS{$code};
  78. }
  79. # parse_args(version => $v, usage => $u, spec => \@s)
  80. sub parse_args
  81. {
  82. my %arg = @_;
  83. foreach (qw(usage version spec)) {
  84. croak "missing required argument '$_'" unless exists $arg{$_};
  85. }
  86. my $usage = sprintf $arg{usage}, $PLUGIN;
  87. $usage .= "\n" if substr($usage,-1) ne "\n";
  88. my $version = $arg{version};
  89. $version .= "\n" if substr($version,-1) ne "\n";
  90. my $spec = $arg{spec};
  91. my $blurb = $arg{blurb} || '';
  92. $blurb .= "\n" if $blurb && substr($blurb,-1) ne "\n";
  93. my $licence = $arg{licence} || $arg{license} || qq(
  94. This nagios plugin is free software, and comes with ABSOLUTELY NO WARRANTY.
  95. It may be used, redistributed and/or modified under the terms of the GNU
  96. General Public Licence (see http://www.fsf.org/licensing/licenses/gpl.txt).
  97. );
  98. $licence .= "\n" if $licence && substr($licence,-1) ne "\n";
  99. my $help_extra = $arg{help_extra};
  100. $help_extra .= "\n" if $help_extra && substr($help_extra,-1) ne "\n";
  101. croak "invalid spec argument - not array ref" unless ref $spec eq 'ARRAY';
  102. croak "odd number of spec elements" unless int(scalar @$spec % 2) == 0;
  103. # Build up options and help text from spec array
  104. my ($show_usage, $show_help, $show_version, @verbose);
  105. my @opt = (
  106. "usage|?" => \$show_usage,
  107. "help|h" => \$show_help,
  108. "version|V" => \$show_version,
  109. "timeout|t=i" => \$TIMEOUT,
  110. "verbose|v" => \@verbose,
  111. );
  112. my $help_tmpl = qq(Options:
  113. -h, --help
  114. Print detailed help screen
  115. -V, --version
  116. Print version information
  117. %s
  118. -t, --timeout=INTEGER
  119. Seconds before plugin times out (default: $TIMEOUT)
  120. -v, --verbose
  121. Show details for command-line debugging
  122. );
  123. my $help = '';
  124. my @req = ();
  125. while (@$spec) {
  126. my $opt = shift @$spec;
  127. my $elt = shift @$spec;
  128. croak "spec element for option '$opt' is not array ref"
  129. unless ref $elt eq 'ARRAY';
  130. my ($var, $help_text, $req) = @$elt;
  131. push @opt, $opt, $var;
  132. $help_text = " $help_text" unless substr($help_text,0,1) eq ' ';
  133. $help_text .= "\n" unless substr($help_text,-1) eq "\n";
  134. $help .= $help_text;
  135. push @req, $var if $req;
  136. }
  137. chomp $help;
  138. $help = sprintf $help_tmpl, $help;
  139. my $result = GetOptions(@opt) || print($usage) && exit;
  140. # Handle standard options
  141. nagios_exit("UNKNOWN", print_revision($version)) if $show_version;
  142. nagios_exit("UNKNOWN", print($usage)) if $show_usage;
  143. nagios_exit("UNKNOWN", print_help($version,$usage,$help,$licence,$blurb,$help_extra))
  144. if $show_help;
  145. # Check required arguments
  146. for (@req) {
  147. if (ref $_ eq 'SCALAR') {
  148. &nagios_exit("UNKNOWN", print($usage)) unless defined $$_;
  149. } elsif (ref $_ eq 'ARRAY') {
  150. &nagios_exit("UNKNOWN", print($usage)) unless @$_;
  151. } else {
  152. die "invalid required reference '$_' - expected scalar ref or array ref only";
  153. }
  154. }
  155. # Setup alarm handler (will handle any alarm($TIMEOUT) for plugin)
  156. $SIG{ALRM} = sub {
  157. &nagios_exit("UNKNOWN", "no response from $PLUGIN (timeout, ${TIMEOUT}s)");
  158. };
  159. $VERBOSE = scalar(@verbose);
  160. }
  161. # exit_results(%arg)
  162. # returns CRITICAL if @{$arg{CRITICAL}}, WARNING if @{$arg{WARNING}}, else OK
  163. # uses $arg{results} for message if defined, else @{$arg{<STATUS>}},
  164. # where <STATUS> is the return code above
  165. sub exit_results
  166. {
  167. my (%arg) = @_;
  168. my %keys = map { $_ => 1 } qw(CRITICAL WARNING OK results);
  169. for (sort keys %arg) {
  170. croak "[Nagios::Plugin::exit_results] invalid argument $_" unless $keys{$_};
  171. }
  172. my $results = '';
  173. my $delim = ' : ';
  174. if ($arg{results}) {
  175. $results = ref $arg{results} eq 'ARRAY' ?
  176. join($delim, @{$arg{results}}) :
  177. $arg{results};
  178. }
  179. if ($arg{CRITICAL} && (ref $arg{CRITICAL} ne 'ARRAY' || @{$arg{CRITICAL}})) {
  180. &nagios_exit("CRITICAL", $results) if $results;
  181. &nagios_exit("CRITICAL", join($delim, @{$arg{CRITICAL}}))
  182. if $arg{CRITICAL} && ref $arg{CRITICAL} eq 'ARRAY' && @{$arg{CRITICAL}};
  183. &nagios_exit("CRITICAL", $arg{CRITICAL}) if $arg{CRITICAL};
  184. }
  185. elsif ($arg{WARNING} && (ref $arg{WARNING} ne 'ARRAY' || @{$arg{WARNING}})) {
  186. &nagios_exit("WARNING", $results) if $results;
  187. &nagios_exit("WARNING", join($delim, @{$arg{WARNING}}))
  188. if $arg{WARNING} && ref $arg{WARNING} eq 'ARRAY' && @{$arg{WARNING}};
  189. &nagios_exit("WARNING", $arg{WARNING}) if $arg{WARNING};
  190. }
  191. &nagios_exit("OK", $results) if $results;
  192. &nagios_exit("OK", join($delim, @{$arg{OK}}))
  193. if $arg{OK} && ref $arg{OK} eq 'ARRAY' && @{$arg{OK}};
  194. &nagios_exit("OK", $arg{OK}) if $arg{OK};
  195. &nagios_exit("OK", "All okay");
  196. }
  197. # ------------------------------------------------------------------------
  198. 1;
  199. __END__
  200. =head1 NAME
  201. Nagios::Plugin - Perl module for creating nagios plugins
  202. =head1 SYNOPSIS
  203. # Nagios::Plugin exports $PLUGIN, $TIMEOUT, and $VERBOSE variables,
  204. # and three subroutines by default: parse_args(), nagios_exit(),
  205. # and exit_results(). load_config() can also be imported explicitly.
  206. use Nagios::Plugin;
  207. use Nagios::Plugin qw(:std load_config);
  208. # parse_args - parse @ARGV for std args and args in @spec
  209. parse_args(
  210. version => 0.01,
  211. usage => 'usage: %s -w <warn> -c <crit>',
  212. spec => \@spec,
  213. );
  214. # nagios_exit($code, $msg)
  215. # where $code is qw(OK WARNING CRITICAL UNKNOWN DEPENDENT)
  216. nagios_exit("CRITICAL", "You're ugly and your mother dresses you funny");
  217. # exit_results - exit based on the given arrays
  218. exit_results(
  219. CRITICAL => \@crit,
  220. WARNING => \@warn,
  221. OK => $ok_message,
  222. );
  223. # load_config - load $section section of plugins.cfg config file
  224. # If not set, $section default to plugin name.
  225. $config = load_config();
  226. $config = load_config($section);
  227. =head1 DESCRIPTION
  228. Nagios::Plugin is a perl module for simplifying the creation of
  229. nagios plugins, mainly by standardising some of the argument parsing
  230. and handling stuff most plugins require.
  231. Nagios::Plugin exports the following variables:
  232. =over 4
  233. =item $PLUGIN
  234. The name of the plugin i.e. basename($0).
  235. =item $TIMEOUT
  236. The number of seconds before the plugin times out, set via the -t argument.
  237. =item $VERBOSE
  238. The number of -v arguments to the plugin.
  239. =back
  240. Nagios::Plugin also exports three subroutines by default: parse_args(),
  241. for parsing @ARGV for std and supplied args; nagios_exit(), for returning
  242. a standard Nagios return status plus a message; and exit_results(), for
  243. checking a set of message arrays and exiting appropriately. The following
  244. subroutines can also be imported explicitly: load_config(), for loading
  245. a set of config settings from the plugins.cfg config file.
  246. =head2 parse_args
  247. The parse_args subroutine provides the core Nagios::Plugin functionality,
  248. and should be called early in your plugin. It uses a named argument
  249. syntax, and currently takes three arguments: the version number ('version');
  250. a short usage message ('usage', newlines okay, %s will be substituted with
  251. $PLUGIN); and an argument spec for any additional arguments your plugin
  252. will accept.
  253. Nagios::Plugin provides standard argument handling for the following
  254. arguments:
  255. =over 4
  256. =item --usage | -?
  257. Print a short usage message for the plugin.
  258. =item --help | -h
  259. Print a longer help message, include the version number, the usage
  260. message, and help text for the individual arguments.
  261. =item --version | -V
  262. Print the plugin version number and licence information (currently
  263. hardcoded).
  264. =item --timeout | -t
  265. Number of seconds for plugin timeout (if the plugin implements one);
  266. default: 15.
  267. =item --verbose | -v
  268. Turn on verbose debug output (may be repeated - the exported $VERBOSE
  269. variable is set to the number of -v arguments parsed).
  270. =back
  271. To define additional arguments for your plugin, you fill out an
  272. argument specifier, which is just an arrayref of argument definitions.
  273. Each definition is basically an extended Getopt::Long definition -
  274. instead of the two-item tuple $option_defn => $variable used in
  275. Getopt::Long, Nagios::Plugin uses a three- or four-item tuple which
  276. also includes help text for argument, and optionally an additional
  277. mandatoriness flag - the syntax used is:
  278. $option_defn => [ $variable, $help_text, $required_flag ]
  279. e.g.
  280. parse_args(
  281. version => 0.01,
  282. usage => 'usage: %s -w <warn> -c <crit>',
  283. spec => [
  284. "warning|w=s" => [
  285. \$warning,
  286. q(-w, --warning=INTEGER\n Exit with WARNING status if less than INTEGER foobars are free),
  287. 'REQUIRED',
  288. ],
  289. "critical|c=s" => [
  290. \$critical,
  291. q(-c, --critical=INTEGER\n Exit with CRITICAL status if less than INTEGER foobars are free),
  292. 'REQUIRED',
  293. ],
  294. ],
  295. );
  296. =head2 nagios_exit
  297. Convenience function, to exit with the given nagios status code
  298. and message:
  299. nagios_exit(OK => 'query successful');
  300. nagios_exit("CRITICAL", "You're ugly and your mother dresses you funny");
  301. Valid status codes are "OK", "WARNING", "CRITICAL", "UNKNOWN".
  302. =head2 exit_results
  303. exit_results exits from the plugin after examining a supplied set of
  304. arrays. Syntax is:
  305. exit_results(
  306. CRITICAL => \@crit,
  307. WARNING => \@warn,
  308. OK => $ok_message, # or \@ok_messages
  309. );
  310. exit_results returns 'CRITICAL' if the @crit array is non-empty;
  311. 'WARNING' if the @warn array is non-empty; and otherwise 'OK'. The
  312. text returned is typically the joined contents of @crit or @warn or
  313. @ok_messages (or $ok_message).
  314. Sometimes on error or warning you want to return more than just the
  315. error cases in the returned text. You can do this by passing a
  316. 'results' parameter containing the string or strings you want to use
  317. for all status codes e.g.
  318. # Use the given $results string on CRITICAL, WARNING, and OK
  319. exit_results(
  320. CRITICAL => \@crit,
  321. WARNING => \@warn,
  322. results => $results # or \@results
  323. );
  324. =head2 load_config
  325. Load a hashref of config variables from the given section of the
  326. plugins.cfg config file. Section defaults to plugin name.
  327. e.g.
  328. $config = load_config();
  329. $config = load_config('prod_db');
  330. =head1 CHANGES
  331. Versions prior to 0.03 overrode the standard exit() function instead
  332. of using a separate nagios_exit. This breaks under ePN with Nagios 2.0,
  333. so the change to nagios_exit was made. Thanks to Håkon Løvdal for the
  334. problem report.
  335. The auto-exported $CONFIG variable was removed in 0.04, replaced with
  336. the load_config function, again due to problems running under ePN.
  337. =head1 AUTHOR
  338. Gavin Carr <gavin@openfusion.com.au>
  339. =head1 LICENCE
  340. Copyright 2005-2006 Gavin Carr. All Rights Reserved.
  341. This module is free software. It may be used, redistributed
  342. and/or modified under either the terms of the Perl Artistic
  343. License (see http://www.perl.com/perl/misc/Artistic.html)
  344. or the GNU General Public Licence (see
  345. http://www.fsf.org/licensing/licenses/gpl.txt).
  346. =cut
  347. # arch-tag: 1495e893-2a66-4e61-a8eb-8bfa401b2a4f
  348. # vim:ft=perl:ai:sw=2