summaryrefslogtreecommitdiffstats
path: root/lib/Nagios
diff options
context:
space:
mode:
authorGavin Carr <gonzai@users.sourceforge.net>2007-03-21 00:52:56 +0000
committerGavin Carr <gonzai@users.sourceforge.net>2007-03-21 00:52:56 +0000
commitdc31f1cd3841d486e920e59ce42e888ca94e4289 (patch)
tree14bcc87e8349b99b01a649f27429690321fc21f9 /lib/Nagios
parentc6cbf050974c8f6642fa1d7bde309710b66cbfa0 (diff)
downloadmonitoring-plugin-perl-dc31f1cd3841d486e920e59ce42e888ca94e4289.tar.gz
Finished initial --extra-opts support; added Getopt spec-to-help and multiline help support.
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/Nagios-Plugin/trunk@1643 f882894a-f735-0410-b71e-b25c423dba1c
Diffstat (limited to 'lib/Nagios')
-rw-r--r--lib/Nagios/Plugin/Config.pm170
-rw-r--r--lib/Nagios/Plugin/Functions.pm10
-rw-r--r--lib/Nagios/Plugin/Getopt.pm263
3 files changed, 372 insertions, 71 deletions
diff --git a/lib/Nagios/Plugin/Config.pm b/lib/Nagios/Plugin/Config.pm
new file mode 100644
index 0000000..92193c2
--- /dev/null
+++ b/lib/Nagios/Plugin/Config.pm
@@ -0,0 +1,170 @@
1package Nagios::Plugin::Config;
2
3use strict;
4use Carp;
5use File::Spec;
6use base qw(Config::Tiny);
7
8my $FILENAME1 = 'plugins.ini';
9my $FILENAME2 = 'nagios-plugins.ini';
10
11# Config paths ending in nagios (search for $FILENAME1)
12my @NAGIOS_CONFIG_PATH = qw(/etc/nagios /usr/local/nagios/etc /usr/local/etc/nagios /etc/opt/nagios);
13# Config paths not ending in nagios (search for $FILENAME2)
14my @CONFIG_PATH = qw(/etc /usr/local/etc /etc/opt);
15
16# Override Config::Tiny::read to default the filename, if not given
17sub read
18{
19 my $class = shift;
20
21 unless ($_[0]) {
22 SEARCH: {
23 if ($ENV{NAGIOS_CONFIG_PATH}) {
24 for (split /:/, $ENV{NAGIOS_CONFIG_PATH}) {
25 my $file = File::Spec->catfile($_, $FILENAME1);
26 unshift(@_, $file), last SEARCH if -f $file;
27 $file = File::Spec->catfile($_, $FILENAME2);
28 unshift(@_, $file), last SEARCH if -f $file;
29 }
30 }
31 for (@NAGIOS_CONFIG_PATH) {
32 my $file = File::Spec->catfile($_, $FILENAME1);
33 unshift(@_, $file), last SEARCH if -f $file;
34 }
35 for (@CONFIG_PATH) {
36 my $file = File::Spec->catfile($_, $FILENAME2);
37 unshift(@_, $file), last SEARCH if -f $file;
38 }
39 }
40
41 croak "Cannot find '$FILENAME1' or '$FILENAME2' in any standard location." unless $_[0];
42 }
43
44 $class->SUPER::read( @_ );
45}
46
47# Straight from Config::Tiny - only changes are repeated property key support
48# Would be nice if we could just override the per-line handling ...
49sub read_string
50{
51 my $class = ref $_[0] ? ref shift : shift;
52 my $self = bless {}, $class;
53 return undef unless defined $_[0];
54
55 # Parse the file
56 my $ns = '_';
57 my $counter = 0;
58 foreach ( split /(?:\015{1,2}\012|\015|\012)/, shift ) {
59 $counter++;
60
61 # Skip comments and empty lines
62 next if /^\s*(?:\#|\;|$)/;
63
64 # Handle section headers
65 if ( /^\s*\[\s*(.+?)\s*\]\s*$/ ) {
66 # Create the sub-hash if it doesn't exist.
67 # Without this sections without keys will not
68 # appear at all in the completed struct.
69 $self->{$ns = $1} ||= {};
70 next;
71 }
72
73 # Handle properties
74 if ( /^\s*([^=]+?)\s*=\s*(.*?)\s*$/ ) {
75 $self->{$ns}->{$1} = defined $self->{$ns}->{$1} ?
76 [ $self->{$ns}->{$1}, $2 ] :
77 $2;
78 next;
79 }
80
81 return $self->_error( "Syntax error at line $counter: '$_'" );
82 }
83
84 $self;
85}
86
87sub write { croak "Write access not permitted" }
88
891;
90
91=head1 NAME
92
93Nagios::Plugin::Config - read nagios plugin .ini style config files
94
95=head1 SYNOPSIS
96
97 # Read given nagios plugin config file
98 $Config = Nagios::Plugin::Config->read( '/etc/nagios/plugins.ini' );
99
100 # Search for and read default nagios plugin config file
101 $Config = Nagios::Plugin::Config->read();
102
103 # Access sections and properties (returns scalars or arrayrefs)
104 $rootproperty = $Config->{_}->{rootproperty};
105 $one = $Config->{section}->{one};
106 $Foo = $Config->{section}->{Foo};
107
108=head1 DESCRIPTION
109
110Nagios::Plugin::Config is a subclass of the excellent Config::Tiny,
111with the following changes:
112
113=over 4
114
115=item
116
117Repeated keys are allowed within sections, returning lists instead of scalars
118
119=item
120
121Write functionality has been removed i.e. access is read only
122
123=item
124
125Nagios::Plugin::Config searches for a default nagios plugins file if no explicit
126filename is given to C<read()>. The current standard locations checked are:
127
128=over 4
129
130=item /etc/nagios/plugins.ini
131
132=item /usr/local/nagios/etc/plugins.ini
133
134=item /usr/local/etc/nagios /etc/opt/nagios/plugins.ini
135
136=item /etc/nagios-plugins.ini
137
138=item /usr/local/etc/nagios-plugins.ini
139
140=item /etc/opt/nagios-plugins.ini
141
142=back
143
144To use a custom location, set a C<NAGIOS_CONFIG_PATH> environment variable
145to the set of directories that should be checked. The first C<plugins.ini> or
146C<nagios-plugins.ini> file found will be used.
147
148=back
149
150
151=head1 SEE ALSO
152
153L<Config::Tiny>, L<Nagios::Plugin>
154
155
156=head1 AUTHORS
157
158This code is maintained by the Nagios Plugin Development Team:
159L<http://nagiosplug.sourceforge.net>.
160
161
162=head1 COPYRIGHT and LICENCE
163
164Copyright (C) 2006-2007 by Nagios Plugin Development Team
165
166This library is free software; you can redistribute it and/or modify
167it under the same terms as Perl itself.
168
169=cut
170
diff --git a/lib/Nagios/Plugin/Functions.pm b/lib/Nagios/Plugin/Functions.pm
index 526dbed..751251f 100644
--- a/lib/Nagios/Plugin/Functions.pm
+++ b/lib/Nagios/Plugin/Functions.pm
@@ -46,6 +46,13 @@ our %STATUS_TEXT = reverse %ERRORS;
46my $_fake_exit = 0; 46my $_fake_exit = 0;
47sub _fake_exit { @_ ? $_fake_exit = shift : $_fake_exit }; 47sub _fake_exit { @_ ? $_fake_exit = shift : $_fake_exit };
48 48
49# Tweak default die handling: die is cool because it allows capturing both return codes and
50# output via eval, but the Nagios Plugin Guidelines like STDOUT over STDERR
51$SIG{__DIE__} = sub {
52 print STDOUT shift;
53 exit $!;
54};
55
49sub get_shortname { 56sub get_shortname {
50 my %arg = @_; 57 my %arg = @_;
51 58
@@ -390,7 +397,6 @@ This code is maintained by the Nagios Plugin Development Team: http://nagiosplug
390Copyright (C) 2006 by Nagios Plugin Development Team 397Copyright (C) 2006 by Nagios Plugin Development Team
391 398
392This library is free software; you can redistribute it and/or modify 399This library is free software; you can redistribute it and/or modify
393it under the same terms as Perl itself, either Perl version 5.8.4 or, 400it under the same terms as Perl itself.
394at your option, any later version of Perl 5 you may have available.
395 401
396=cut 402=cut
diff --git a/lib/Nagios/Plugin/Getopt.pm b/lib/Nagios/Plugin/Getopt.pm
index 806a6a0..743bf7e 100644
--- a/lib/Nagios/Plugin/Getopt.pm
+++ b/lib/Nagios/Plugin/Getopt.pm
@@ -10,15 +10,13 @@ use File::Basename;
10use Getopt::Long qw(:config no_ignore_case bundling); 10use Getopt::Long qw(:config no_ignore_case bundling);
11use Carp; 11use Carp;
12use Params::Validate qw(:all); 12use Params::Validate qw(:all);
13use Config::Tiny;
14use base qw(Class::Accessor); 13use base qw(Class::Accessor);
15 14
16use Nagios::Plugin::Functions; 15use Nagios::Plugin::Functions;
17use vars qw($VERSION $DEFAULT_CONFIG_FILE); 16use Nagios::Plugin::Config;
17use vars qw($VERSION);
18$VERSION = $Nagios::Plugin::Functions::VERSION; 18$VERSION = $Nagios::Plugin::Functions::VERSION;
19 19
20$DEFAULT_CONFIG_FILE = '/etc/nagios/plugins.cfg';
21
22# Standard defaults 20# Standard defaults
23my %DEFAULT = ( 21my %DEFAULT = (
24 timeout => 15, 22 timeout => 15,
@@ -39,8 +37,8 @@ my @ARGS = ({
39 spec => 'version|V', 37 spec => 'version|V',
40 help => "-V, --version\n Print version information", 38 help => "-V, --version\n Print version information",
41 }, { 39 }, {
42 spec => 'default-opts:s@', 40 spec => 'extra-opts:s@',
43 help => "--default-opts=[<section>[@<config_file>]]\n Section and/or config_file from which to load default options (may repeat)", 41 help => "--extra-opts=[<section>[@<config_file>]]\n Section and/or config_file from which to load extra options (may repeat)",
44 }, { 42 }, {
45 spec => 'timeout|t=i', 43 spec => 'timeout|t=i',
46 help => "-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)", 44 help => "-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)",
@@ -77,6 +75,37 @@ sub _attr
77 $self->{_attr}->{$item} . "\n" . $extra; 75 $self->{_attr}->{$item} . "\n" . $extra;
78} 76}
79 77
78# Turn argument spec into help-style output
79sub _spec_to_help
80{
81 my ($self, $spec, $label) = @_;
82
83 my ($opts, $type) = split /=/, $spec, 2;
84 my (@short, @long);
85 for (split /\|/, $opts) {
86 if (length $_ == 1) {
87 push @short, "-$_";
88 } else {
89 push @long, "--$_";
90 }
91 }
92
93 my $help = join(', ', @short, @long);
94 if ($type) {
95 if ($label) {
96 $help .= '=' . $label;
97 }
98 else {
99 $help .= $type eq 'i' ? '=INTEGER' : '=STRING';
100 }
101 }
102 elsif ($label) {
103 carp "Label specified, but there's no type in spec '$spec'";
104 }
105 $help .= "\n ";
106 return $help;
107}
108
80# Options output for plugin -h 109# Options output for plugin -h
81sub _options 110sub _options
82{ 111{
@@ -94,10 +123,29 @@ sub _options
94 123
95 my @options = (); 124 my @options = ();
96 for my $arg (@args, @defer) { 125 for my $arg (@args, @defer) {
97 if ($arg->{help} =~ m/%s/) { 126 my $help_array = ref $arg->{help} && ref $arg->{help} eq 'ARRAY' ? $arg->{help} : [ $arg->{help} ];
98 push @options, sprintf($arg->{help}, $arg->{default} || ''); 127 my $label_array = $arg->{label} && ref $arg->{label} && ref $arg->{label} eq 'ARRAY' ? $arg->{label} : [ $arg->{label} ];
128 my $help_string = '';
129 for (my $i = 0; $i <= $#$help_array; $i++) {
130 my $help = $help_array->[$i];
131 # Add spec arguments to help if not already there
132 if ($help =~ m/^\s*-/) {
133 $help_string .= $help;
134 }
135 else {
136 $help_string .= $self->_spec_to_help($arg->{spec}, $label_array->[$i]) . $help;
137 $help_string .= "\n " if $i < $#$help_array;
138 }
139 }
140
141 # Add help_string to @options
142 if ($help_string =~ m/%s/) {
143 my $default = defined $arg->{default} ? $arg->{default} : '';
144 # We only handle '%s' formats here, so escape everything else
145 $help_string =~ s/%(?!s)/%%/g;
146 push @options, sprintf($help_string, $default, $default, $default, $default);
99 } else { 147 } else {
100 push @options, $arg->{help}; 148 push @options, $help_string;
101 } 149 }
102 } 150 }
103 151
@@ -195,15 +243,12 @@ sub _load_config_section
195 my $self = shift; 243 my $self = shift;
196 my ($section, $file, $flags) = @_; 244 my ($section, $file, $flags) = @_;
197 $section ||= $self->{_attr}->{plugin}; 245 $section ||= $self->{_attr}->{plugin};
198 $file ||= $DEFAULT_CONFIG_FILE;
199
200 $self->_die("Cannot find config file '$file'") if $flags->{fatal} && ! -f $file;
201 246
202 my $Config = Config::Tiny->read($file); 247 my $Config = Nagios::Plugin::Config->read($file);
203 $self->_die("Cannot read config file '$file'") unless defined $Config;
204 248
249 # TODO: is this check sane? Does --extra-opts=foo require a [foo] section?
205 $self->_die("Invalid section '$section' in config file '$file'") 250 $self->_die("Invalid section '$section' in config file '$file'")
206 if $flags->{fatal} && ! exists $Config->{$section}; 251 unless exists $Config->{$section};
207 252
208 return $Config->{$section}; 253 return $Config->{$section};
209} 254}
@@ -248,7 +293,7 @@ sub _cmdline
248 293
249 # Skip defaults and internals 294 # Skip defaults and internals
250 next if exists $DEFAULT{$key} && $hash->{$key} eq $DEFAULT{$key}; 295 next if exists $DEFAULT{$key} && $hash->{$key} eq $DEFAULT{$key};
251 next if grep { $key eq $_ } qw(help usage version default-opts); 296 next if grep { $key eq $_ } qw(help usage version extra-opts);
252 next unless defined $hash->{$key}; 297 next unless defined $hash->{$key};
253 298
254 # Render arg 299 # Render arg
@@ -275,44 +320,37 @@ sub _cmdline
275 return wantarray ? @args : join(' ', @args); 320 return wantarray ? @args : join(' ', @args);
276} 321}
277 322
278# Process and load default-opts sections 323# Process and load extra-opts sections
279sub _process_default_opts 324sub _process_extra_opts
280{ 325{
281 my $self = shift; 326 my $self = shift;
282 my ($args) = @_; 327 my ($args) = @_;
283 328
284 my $defopts_list = $args->{'default-opts'}; 329 my $extopts_list = $args->{'extra-opts'};
285 my $defopts_explicit = 1;
286
287 # If no default_opts defined, force one implicitly
288 if (! $defopts_list) {
289 $defopts_list = [ '' ];
290 $defopts_explicit = 0;
291 }
292 330
293 my @sargs = (); 331 my @sargs = ();
294 for my $defopts (@$defopts_list) { 332 for my $extopts (@$extopts_list) {
295 $defopts ||= $self->{_attr}->{plugin}; 333 $extopts ||= $self->{_attr}->{plugin};
296 my $section = $defopts; 334 my $section = $extopts;
297 my $file = ''; 335 my $file = '';
298 336
299 # Parse section@file 337 # Parse section@file
300 if ($defopts =~ m/^(\w*)@(.*?)\s*$/) { 338 if ($extopts =~ m/^(\w*)@(.*?)\s*$/) {
301 $section = $1; 339 $section = $1;
302 $file = $2; 340 $file = $2;
303 } 341 }
304 342
305 # Load section args 343 # Load section args
306 my $shash = $self->_load_config_section($section, $file, { fatal => $defopts_explicit }); 344 my $shash = $self->_load_config_section($section, $file);
307 345
308 # Turn $shash into a series of commandline-like arguments 346 # Turn $shash into a series of commandline-like arguments
309 push @sargs, $self->_cmdline($shash); 347 push @sargs, $self->_cmdline($shash);
310 } 348 }
311 349
312 # Reset ARGV to default-opts + original 350 # Reset ARGV to extra-opts + original
313 @ARGV = ( @sargs, @{$self->{_attr}->{argv}} ); 351 @ARGV = ( @sargs, @{$self->{_attr}->{argv}} );
314 352
315 printf "[default-opts] %s %s\n", $self->{_attr}->{plugin}, join(' ', @ARGV) 353 printf "[extra-opts] %s %s\n", $self->{_attr}->{plugin}, join(' ', @ARGV)
316 if $args->{verbose} && $args->{verbose} >= 3; 354 if $args->{verbose} && $args->{verbose} >= 3;
317} 355}
318 356
@@ -332,17 +370,19 @@ sub arg
332 help => 1, 370 help => 1,
333 default => 0, 371 default => 0,
334 required => 0, 372 required => 0,
373 label => 0,
335 }); 374 });
336 } 375 }
337 376
338 # Positional args 377 # Positional args
339 else { 378 else {
340 my @args = validate_pos(@_, 1, 1, 0, 0); 379 my @args = validate_pos(@_, 1, 1, 0, 0, 0);
341 %args = ( 380 %args = (
342 spec => $args[0], 381 spec => $args[0],
343 help => $args[1], 382 help => $args[1],
344 default => $args[2], 383 default => $args[2],
345 required => $args[3], 384 required => $args[3],
385 label => $args[4],
346 ); 386 );
347 } 387 }
348 388
@@ -358,7 +398,7 @@ sub getopts
358 # Collate spec arguments for Getopt::Long 398 # Collate spec arguments for Getopt::Long
359 my @opt_array = $self->_process_specs_getopt_long; 399 my @opt_array = $self->_process_specs_getopt_long;
360 400
361 # Capture original @ARGV (for default-opts games) 401 # Capture original @ARGV (for extra-opts games)
362 $self->{_attr}->{argv} = [ @ARGV ]; 402 $self->{_attr}->{argv} = [ @ARGV ];
363 403
364 # Call GetOptions using @opt_array 404 # Call GetOptions using @opt_array
@@ -367,10 +407,10 @@ sub getopts
367 # Invalid options - give usage message and exit 407 # Invalid options - give usage message and exit
368 $self->_die($self->_usage) unless $ok; 408 $self->_die($self->_usage) unless $ok;
369 409
370 # Process default-opts 410 # Process extra-opts
371 $self->_process_default_opts($args1); 411 $self->_process_extra_opts($args1);
372 412
373 # Call GetOptions again, this time including default-opts 413 # Call GetOptions again, this time including extra-opts
374 $ok = GetOptions($self, @opt_array); 414 $ok = GetOptions($self, @opt_array);
375 # Invalid options - give usage message and exit 415 # Invalid options - give usage message and exit
376 $self->_die($self->_usage) unless $ok; 416 $self->_die($self->_usage) unless $ok;
@@ -410,7 +450,7 @@ sub _init
410 plugin => { default => $plugin }, 450 plugin => { default => $plugin },
411 blurb => 0, 451 blurb => 0,
412 extra => 0, 452 extra => 0,
413 'default-opts' => 0, 453 'extra-opts' => 0,
414 license => { default => $DEFAULT{license} }, 454 license => { default => $DEFAULT{license} },
415 timeout => { default => $DEFAULT{timeout} }, 455 timeout => { default => $DEFAULT{timeout} },
416 }); 456 });
@@ -452,17 +492,16 @@ processing for Nagios plugins
452 492
453 # Instantiate object (usage is mandatory) 493 # Instantiate object (usage is mandatory)
454 $ng = Nagios::Plugin::Getopt->new( 494 $ng = Nagios::Plugin::Getopt->new(
455 usage => "Usage: %s -H <host> -w <warning_threshold> 495 usage => "Usage: %s -H <host> -w <warning> -c <critical>",
456 -c <critical threshold>", 496 version => '0.1',
457 version => '0.01',
458 url => 'http://www.openfusion.com.au/labs/nagios/', 497 url => 'http://www.openfusion.com.au/labs/nagios/',
459 blurb => 'This plugin tests various stuff.', 498 blurb => 'This plugin tests various stuff.',
460 ); 499 );
461 500
462 # Add argument - named parameters (spec and help are mandatory) 501 # Add argument - named parameters (spec and help are mandatory)
463 $ng->arg( 502 $ng->arg(
464 spec => 'critical|c=s', 503 spec => 'critical|c=i',
465 help => qq(-c, --critical=INTEGER\n Exit with CRITICAL status if fewer than INTEGER foobars are free), 504 help => q(Exit with CRITICAL status if fewer than INTEGER foobars are free),
466 required => 1, 505 required => 1,
467 default => 10, 506 default => 10,
468 ); 507 );
@@ -470,8 +509,8 @@ processing for Nagios plugins
470 # Add argument - positional parameters - arg spec, help text, 509 # Add argument - positional parameters - arg spec, help text,
471 # default value, required? (first two mandatory) 510 # default value, required? (first two mandatory)
472 $ng->arg( 511 $ng->arg(
473 'warning|w=s', 512 'warning|w=i',
474 qq(-w, --warning=INTEGER\n Exit with WARNING status if fewer than INTEGER foobars are free), 513 q(Exit with WARNING status if fewer than INTEGER foobars are free),
475 5, 514 5,
476 1); 515 1);
477 516
@@ -545,9 +584,10 @@ License text, included in the longer --help output (see below for an
545example). By default, this is set to the standard nagios plugins 584example). By default, this is set to the standard nagios plugins
546GPL license text: 585GPL license text:
547 586
548 This nagios plugin is free software, and comes with ABSOLUTELY NO WARRANTY. 587 This nagios plugin is free software, and comes with ABSOLUTELY
549 It may be used, redistributed and/or modified under the terms of the GNU 588 NO WARRANTY. It may be used, redistributed and/or modified under
550 General Public Licence (see http://www.fsf.org/licensing/licenses/gpl.txt). 589 the terms of the GNU General Public Licence (see
590 http://www.fsf.org/licensing/licenses/gpl.txt).
551 591
552Provide your own to replace this text in the help output. 592Provide your own to replace this text in the help output.
553 593
@@ -603,8 +643,8 @@ example:
603 -H, --hostname=ADDRESS 643 -H, --hostname=ADDRESS
604 Host name or IP address 644 Host name or IP address
605 -p, --ports=STRING 645 -p, --ports=STRING
606 Port numbers to check. Format: comma-separated, colons or hyphens for ranges, 646 Port numbers to check. Format: comma-separated, colons for ranges,
607 no spaces e.g. 8700:8705,8710-8715,8760 647 no spaces e.g. 8700:8705,8710:8715,8760
608 -t, --timeout=INTEGER 648 -t, --timeout=INTEGER
609 Seconds before plugin times out (default: 15) 649 Seconds before plugin times out (default: 15)
610 -v, --verbose 650 -v, --verbose
@@ -615,21 +655,25 @@ example:
615 655
616You can define arguments for your plugin using the arg() method, which 656You can define arguments for your plugin using the arg() method, which
617supports both named and positional arguments. In both cases 657supports both named and positional arguments. In both cases
618the 'spec' and 'help' arguments are required, while the 'default' 658the C<spec> and C<help> arguments are required, while the C<label>,
619and 'required' arguments are optional: 659C<default>, and C<required> arguments are optional:
620 660
621 # Define --hello argument (named parameters) 661 # Define --hello argument (named parameters)
622 $ng->arg( 662 $ng->arg(
623 spec => 'hello=s', 663 spec => 'hello|h=s',
624 help => "--hello\n Hello string", 664 help => "Hello string",
625 required => 1, 665 required => 1,
626 ); 666 );
627 667
628 # Define --hello argument (positional parameters) 668 # Define --hello argument (positional parameters)
629 # Parameter order is 'spec', 'help', 'default', 'required?' 669 # Parameter order is 'spec', 'help', 'default', 'required?', 'label'
630 $ng->arg('hello=s', "--hello\n Hello string", undef, 1); 670 $ng->arg('hello|h=s', "Hello parameter (default %s)", 5, 1);
671
672=over 4
631 673
632The 'spec' argument (the first argument in the positional variant) is a 674=item spec
675
676The C<spec> argument (the first argument in the positional variant) is a
633L<Getopt::Long> argument specification. See L<Getopt::Long> for the details, 677L<Getopt::Long> argument specification. See L<Getopt::Long> for the details,
634but basically it is a series of one or more argument names for this argument 678but basically it is a series of one or more argument names for this argument
635(separated by '|'), suffixed with an '=<type>' indicator if the argument 679(separated by '|'), suffixed with an '=<type>' indicator if the argument
@@ -651,24 +695,105 @@ and so on. The following are some examples:
651 695
652=back 696=back
653 697
654The 'help' argument is a string displayed in the --help option list output. 698=item help
655If the string contains a '%s' it will be formatted via L<sprintf> with the 699
656'default' as the argument i.e. 700The C<help> argument is a string displayed in the --help option list output,
701or it can be a list (an arrayref) of such strings, for multi-line help (see
702below).
703
704The help string is munged in two ways:
705
706=over 4
707
708=item
709
710First, if the help string does NOT begins with a '-' sign, it is prefixed
711by an expanded form of the C<spec> argument. For instance, the following
712hello argument:
713
714 $ng->arg(
715 spec => 'hello|h=s',
716 help => "Hello string",
717 );
718
719would be displayed in the help output as:
720
721 -h, --hello=STRING
722 Hello string
723
724where the '-h, --hello=STRING' part is derived from the spec definition
725(by convention with short args first, then long, then label/type, if any).
726
727=item
728
729Second, if the string contains a '%s' it will be formatted via
730C<sprintf> with the 'default' as the argument i.e.
657 731
658 sprintf($help, $default) 732 sprintf($help, $default)
659 733
660A gotcha is that standard percentage signs also need to be escaped 734=back
661(i.e. '%%') in this case. 735
736Multi-line help is useful in cases where an argument can be of different types
737and you want to make this explicit in your help output e.g.
738
739 $ng->arg(
740 spec => 'warning|w=s',
741 help => [
742 'Exit with WARNING status if less than BYTES bytes of disk are free',
743 'Exit with WARNING status if less than PERCENT of disk is free',
744 ],
745 label => [ 'BYTES', 'PERCENT%' ],
746 );
747
748would be displayed in the help output as:
749
750 -w, --warning=BYTES
751 Exit with WARNING status if less than BYTES bytes of disk are free
752 -w, --warning=PERCENT%
753 Exit with WARNING status if less than PERCENT of disk space is free
754
755Note that in this case we've also specified explicit labels in another
756arrayref corresponding to the C<help> one - if this had been omitted
757the types would have defaulted to 'STRING', instead of 'BYTES' and
758'PERCENT%'.
759
760
761=item label
762
763The C<label> argument is a scalar or an arrayref (see 'Multi-line help'
764description above) that overrides the standard type expansion when generating
765help text from the spec definition. By default, C<spec=i> arguments are
766labelled as C<=INTEGER> in the help text, and C<spec=s> arguments are labelled
767as C<=STRING>. By supplying your own C<label> argument you can override these
768standard 'INTEGER' and 'STRING' designations.
769
770For multi-line help, you can supply an ordered list (arrayref) of labels to
771match the list of help strings e.g.
772
773 label => [ 'BYTES', 'PERCENT%' ]
662 774
663The 'default' argument is the default value to be given to this parameter 775Any labels that are left as undef (or just omitted, if trailing) will just
776use the default 'INTEGER' or 'STRING' designations e.g.
777
778 label => [ undef, 'PERCENT%' ]
779
780
781=item default
782
783The C<default> argument is the default value to be given to this parameter
664if none is explicitly supplied. 784if none is explicitly supplied.
665 785
666The 'required' argument is a boolean used to indicate that this argument 786
787=item required
788
789The C<required> argument is a boolean used to indicate that this argument
667is mandatory (Nagios::Plugin::Getopt will exit with your usage message and 790is mandatory (Nagios::Plugin::Getopt will exit with your usage message and
668a 'Missing argument' indicator if any required arguments are not supplied). 791a 'Missing argument' indicator if any required arguments are not supplied).
669 792
793=back
794
670Note that --help lists your arguments in the order they are defined, so 795Note that --help lists your arguments in the order they are defined, so
671you might want to order your arg() calls accordingly. 796you should order your C<arg()> calls accordingly.
672 797
673 798
674=head2 GETOPTS 799=head2 GETOPTS
@@ -703,14 +828,14 @@ using their long variant names.
703 828
704=head2 BUILTIN PROCESSING 829=head2 BUILTIN PROCESSING
705 830
706The getopts() method also handles processing of the immediate builtin 831The C<getopts()> method also handles processing of the immediate builtin
707arguments, namely --usage, --version, --help, as well as checking all 832arguments, namely --usage, --version, --help, as well as checking all
708required arguments have been supplied, so you don't have to handle 833required arguments have been supplied, so you don't have to handle
709those yourself. This means that your plugin will exit from the getopts() 834those yourself. This means that your plugin will exit from the getopts()
710call in these cases - if you want to catch that you can run getopts() 835call in these cases - if you want to catch that you can run getopts()
711within an eval{}. 836within an eval{}.
712 837
713getopts() also sets up a default ALRM timeout handler so you can use an 838C<getopts()> also sets up a default ALRM timeout handler so you can use an
714 839
715 alarm $ng->timeout; 840 alarm $ng->timeout;
716 841
@@ -730,7 +855,7 @@ Gavin Carr <gavin@openfusion.com.au>
730 855
731=head1 COPYRIGHT AND LICENSE 856=head1 COPYRIGHT AND LICENSE
732 857
733Copyright (C) 2006 by the Nagios Plugin Development Team. 858Copyright (C) 2006-2007 by the Nagios Plugin Development Team.
734 859
735This module is free software. It may be used, redistributed 860This module is free software. It may be used, redistributed
736and/or modified under either the terms of the Perl Artistic 861and/or modified under either the terms of the Perl Artistic