summaryrefslogtreecommitdiffstats
path: root/lib/Monitoring/Plugin/Getopt.pm
diff options
context:
space:
mode:
authorSven Nierlein <sven@nierlein.de>2014-01-20 00:54:34 +0100
committerSven Nierlein <sven@nierlein.de>2014-01-20 00:54:34 +0100
commitb418181dfe80dd75169b6e8a619ac1932155dea2 (patch)
treecad9c0ae0eae8e800cfff60555ead06ad33c6856 /lib/Monitoring/Plugin/Getopt.pm
parent1cd8d1c52cbd47121f344c4074aec84653f412ce (diff)
downloadmonitoring-plugin-perl-b418181dfe80dd75169b6e8a619ac1932155dea2.tar.gz
renamed module into Monitoring::Plugin
since the complete monitoring team has been renamed, we also rename this module. Signed-off-by: Sven Nierlein <sven@nierlein.de>
Diffstat (limited to 'lib/Monitoring/Plugin/Getopt.pm')
-rw-r--r--lib/Monitoring/Plugin/Getopt.pm869
1 files changed, 869 insertions, 0 deletions
diff --git a/lib/Monitoring/Plugin/Getopt.pm b/lib/Monitoring/Plugin/Getopt.pm
new file mode 100644
index 0000000..ce1c0f9
--- /dev/null
+++ b/lib/Monitoring/Plugin/Getopt.pm
@@ -0,0 +1,869 @@
1#
2# Monitoring::Plugin::Getopt - OO perl module providing standardised argument
3# processing for nagios plugins
4#
5
6package Monitoring::Plugin::Getopt;
7
8use strict;
9use File::Basename;
10use Getopt::Long qw(:config no_ignore_case bundling);
11use Carp;
12use Params::Validate qw(:all);
13use base qw(Class::Accessor);
14
15use Monitoring::Plugin::Functions;
16use Monitoring::Plugin::Config;
17use vars qw($VERSION);
18$VERSION = $Monitoring::Plugin::Functions::VERSION;
19
20# Standard defaults
21my %DEFAULT = (
22 timeout => 15,
23 verbose => 0,
24 license =>
25"This nagios plugin is free software, and comes with ABSOLUTELY NO WARRANTY.
26It may be used, redistributed and/or modified under the terms of the GNU
27General Public Licence (see http://www.fsf.org/licensing/licenses/gpl.txt).",
28);
29# Standard arguments
30my @ARGS = ({
31 spec => 'usage|?',
32 help => "-?, --usage\n Print usage information",
33 }, {
34 spec => 'help|h',
35 help => "-h, --help\n Print detailed help screen",
36 }, {
37 spec => 'version|V',
38 help => "-V, --version\n Print version information",
39 }, {
40 spec => 'extra-opts:s@',
41 help => "--extra-opts=[section][\@file]\n Read options from an ini file. See http://nagiosplugins.org/extra-opts\n for usage and examples.",
42 }, {
43 spec => 'timeout|t=i',
44 help => "-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)",
45 default => $DEFAULT{timeout},
46 }, {
47 spec => 'verbose|v+',
48 help => "-v, --verbose\n Show details for command-line debugging (can repeat up to 3 times)",
49 default => $DEFAULT{verbose},
50 },
51);
52# Standard arguments we traditionally display last in the help output
53my %DEFER_ARGS = map { $_ => 1 } qw(timeout verbose);
54
55# -------------------------------------------------------------------------
56# Private methods
57
58sub _die
59{
60 my $self = shift;
61 my ($msg) = @_;
62 $msg .= "\n" unless substr($msg, -1) eq "\n";
63 Monitoring::Plugin::Functions::_plugin_exit(3, $msg);
64}
65
66# Return the given attribute, if set, including a final newline
67sub _attr
68{
69 my $self = shift;
70 my ($item, $extra) = @_;
71 $extra = '' unless defined $extra;
72 return '' unless $self->{_attr}->{$item};
73 $self->{_attr}->{$item} . "\n" . $extra;
74}
75
76# Turn argument spec into help-style output
77sub _spec_to_help
78{
79 my ($self, $spec, $label) = @_;
80
81 my ($opts, $type) = split /=/, $spec, 2;
82 my (@short, @long);
83 for (split /\|/, $opts) {
84 if (length $_ == 1) {
85 push @short, "-$_";
86 } else {
87 push @long, "--$_";
88 }
89 }
90
91 my $help = join(', ', @short, @long);
92 if ($type) {
93 if ($label) {
94 $help .= '=' . $label;
95 }
96 else {
97 $help .= $type eq 'i' ? '=INTEGER' : '=STRING';
98 }
99 }
100 elsif ($label) {
101 carp "Label specified, but there's no type in spec '$spec'";
102 }
103 $help .= "\n ";
104 return $help;
105}
106
107# Options output for plugin -h
108sub _options
109{
110 my $self = shift;
111
112 my @args = ();
113 my @defer = ();
114 for (@{$self->{_args}}) {
115 if (exists $DEFER_ARGS{$_->{name}}) {
116 push @defer, $_;
117 } else {
118 push @args, $_;
119 }
120 }
121
122 my @options = ();
123 for my $arg (@args, @defer) {
124 my $help_array = ref $arg->{help} && ref $arg->{help} eq 'ARRAY' ? $arg->{help} : [ $arg->{help} ];
125 my $label_array = $arg->{label} && ref $arg->{label} && ref $arg->{label} eq 'ARRAY' ? $arg->{label} : [ $arg->{label} ];
126 my $help_string = '';
127 for (my $i = 0; $i <= $#$help_array; $i++) {
128 my $help = $help_array->[$i];
129 # Add spec arguments to help if not already there
130 if ($help =~ m/^\s*-/) {
131 $help_string .= $help;
132 }
133 else {
134 $help_string .= $self->_spec_to_help($arg->{spec}, $label_array->[$i]) . $help;
135 $help_string .= "\n " if $i < $#$help_array;
136 }
137 }
138
139 # Add help_string to @options
140 if ($help_string =~ m/%s/) {
141 my $default = defined $arg->{default} ? $arg->{default} : '';
142 # We only handle '%s' formats here, so escape everything else
143 $help_string =~ s/%(?!s)/%%/g;
144 push @options, sprintf($help_string, $default, $default, $default, $default);
145 } else {
146 push @options, $help_string;
147 }
148 }
149
150 return ' ' . join("\n ", @options);
151}
152
153# Output for plugin -? (or missing/invalid args)
154sub _usage
155{
156 my $self = shift;
157 sprintf $self->_attr('usage'), $self->{_attr}->{plugin};
158}
159
160# Output for plugin -V
161sub _revision
162{
163 my $self = shift;
164 my $revision = sprintf "%s %s", $self->{_attr}->{plugin}, $self->{_attr}->{version};
165 $revision .= sprintf " [%s]", $self->{_attr}->{url} if $self->{_attr}->{url};
166 $revision .= "\n";
167 $revision;
168}
169
170# Output for plugin -h
171sub _help
172{
173 my $self = shift;
174 my $help = '';
175 $help .= $self->_revision . "\n";
176 $help .= $self->_attr('license', "\n");
177 $help .= $self->_attr('blurb', "\n");
178 $help .= $self->_usage ? $self->_usage . "\n" : '';
179 $help .= $self->_options ? $self->_options . "\n" : '';
180 $help .= $self->_attr('extra', "\n");
181 return $help;
182}
183
184# Return a Getopt::Long-compatible option array from the current set of specs
185sub _process_specs_getopt_long
186{
187 my $self = shift;
188
189 my @opts = ();
190 for my $arg (@{$self->{_args}}) {
191 push @opts, $arg->{spec};
192 # Setup names and defaults
193 my $spec = $arg->{spec};
194 # Use first arg as name (like Getopt::Long does)
195 $spec =~ s/[=:].*$//;
196 my $name = (split /\s*\|\s*/, $spec)[0];
197 $arg->{name} = $name;
198 if (defined $self->{$name}) {
199 $arg->{default} = $self->{$name};
200 } else {
201 $self->{$name} = $arg->{default};
202 }
203 }
204
205 return @opts;
206}
207
208# Check for existence of required arguments
209sub _check_required_opts
210{
211 my $self = shift;
212
213 my @missing = ();
214 for my $arg (@{$self->{_args}}) {
215 if ($arg->{required} && ! defined $self->{$arg->{name}}) {
216 push @missing, $arg->{name};
217 }
218 }
219 if (@missing) {
220 $self->_die($self->_usage . "\n" .
221 join("\n", map { sprintf "Missing argument: %s", $_ } @missing) . "\n");
222 }
223}
224
225# Process and handle any immediate options
226sub _process_opts
227{
228 my $self = shift;
229
230 # Print message and exit for usage, version, help
231 $self->_die($self->_usage) if $self->{usage};
232 $self->_die($self->_revision) if $self->{version};
233 $self->_die($self->_help) if $self->{help};
234}
235
236# -------------------------------------------------------------------------
237# Default opts methods
238
239sub _load_config_section
240{
241 my $self = shift;
242 my ($section, $file, $flags) = @_;
243 $section ||= $self->{_attr}->{plugin};
244
245 my $Config;
246 eval { $Config = Monitoring::Plugin::Config->read($file); };
247 $self->_die($@) if ($@); #TODO: add test?
248
249 # TODO: is this check sane? Does --extra-opts=foo require a [foo] section?
250 ## Nevertheless, if we die as UNKNOWN here we should do the same on default
251 ## file *added eval/_die above*.
252 $file ||= $Config->np_getfile();
253 $self->_die("Invalid section '$section' in config file '$file'")
254 unless exists $Config->{$section};
255
256 return $Config->{$section};
257}
258
259# Helper method to setup a hash of spec definitions for _cmdline
260sub _setup_spec_index
261{
262 my $self = shift;
263 return if defined $self->{_spec};
264 $self->{_spec} = { map { $_->{name} => $_->{spec} } @{$self->{_args}} };
265}
266
267# Quote values that require it
268sub _cmdline_value
269{
270 my $self = shift;
271 local $_ = shift;
272 if (m/\s/ && (m/^[^"']/ || m/[^"']$/)) {
273 return qq("$_");
274 }
275 elsif ($_ eq '') {
276 return q("");
277 }
278 else {
279 return $_;
280 }
281}
282
283# Helper method to format key/values in $hash in a quasi-commandline format
284sub _cmdline
285{
286 my $self = shift;
287 my ($hash) = @_;
288 $hash ||= $self;
289
290 $self->_setup_spec_index;
291
292 my @args = ();
293 for my $key (sort keys %$hash) {
294 # Skip internal keys
295 next if $key =~ m/^_/;
296
297 # Skip defaults and internals
298 next if exists $DEFAULT{$key} && $hash->{$key} eq $DEFAULT{$key};
299 next if grep { $key eq $_ } qw(help usage version extra-opts);
300 next unless defined $hash->{$key};
301
302 # Render arg
303 my $spec = $self->{_spec}->{$key} || '';
304 if ($spec =~ m/[=:].+$/) {
305 # Arg takes value - may be a scalar or an arrayref
306 for my $value (ref $hash->{$key} eq 'ARRAY' ? @{$hash->{$key}} : ( $hash->{$key} )) {
307 $value = $self->_cmdline_value($value);
308 if (length($key) > 1) {
309 push @args, sprintf "--%s=%s", $key, $value;
310 }
311 else {
312 push @args, "-$key", $value;
313 }
314 }
315 }
316
317 else {
318 # Flag - render long or short based on option length
319 push @args, (length($key) > 1 ? '--' : '-') . $key;
320 }
321 }
322
323 return wantarray ? @args : join(' ', @args);
324}
325
326# Process and load extra-opts sections
327sub _process_extra_opts
328{
329 my $self = shift;
330 my ($args) = @_;
331
332 my $extopts_list = $args->{'extra-opts'};
333
334 my @sargs = ();
335 for my $extopts (@$extopts_list) {
336 $extopts ||= $self->{_attr}->{plugin};
337 my $section = $extopts;
338 my $file = '';
339
340 # Parse section@file
341 if ($extopts =~ m/^([^@]*)@(.*?)\s*$/) {
342 $section = $1;
343 $file = $2;
344 }
345
346 # Load section args
347 my $shash = $self->_load_config_section($section, $file);
348
349 # Turn $shash into a series of commandline-like arguments
350 push @sargs, $self->_cmdline($shash);
351 }
352
353 # Reset ARGV to extra-opts + original
354 @ARGV = ( @sargs, @{$self->{_attr}->{argv}} );
355
356 printf "[extra-opts] %s %s\n", $self->{_attr}->{plugin}, join(' ', @ARGV)
357 if $args->{verbose} && $args->{verbose} >= 3;
358}
359
360# -------------------------------------------------------------------------
361# Public methods
362
363# Define plugin argument
364sub arg
365{
366 my $self = shift;
367 my %args;
368
369 # Named args
370 if ($_[0] =~ m/^(spec|help|required|default)$/ && scalar(@_) % 2 == 0) {
371 %args = validate( @_, {
372 spec => 1,
373 help => 1,
374 default => 0,
375 required => 0,
376 label => 0,
377 });
378 }
379
380 # Positional args
381 else {
382 my @args = validate_pos(@_, 1, 1, 0, 0, 0);
383 %args = (
384 spec => $args[0],
385 help => $args[1],
386 default => $args[2],
387 required => $args[3],
388 label => $args[4],
389 );
390 }
391
392 # Add to private args arrayref
393 push @{$self->{_args}}, \%args;
394}
395
396# Process the @ARGV array using the current _args list (possibly exiting)
397sub getopts
398{
399 my $self = shift;
400
401 # Collate spec arguments for Getopt::Long
402 my @opt_array = $self->_process_specs_getopt_long;
403
404 # Capture original @ARGV (for extra-opts games)
405 $self->{_attr}->{argv} = [ @ARGV ];
406
407 # Call GetOptions using @opt_array
408 my $args1 = {};
409 my $ok = GetOptions($args1, @opt_array);
410 # Invalid options - give usage message and exit
411 $self->_die($self->_usage) unless $ok;
412
413 # Process extra-opts
414 $self->_process_extra_opts($args1);
415
416 # Call GetOptions again, this time including extra-opts
417 $ok = GetOptions($self, @opt_array);
418 # Invalid options - give usage message and exit
419 $self->_die($self->_usage) unless $ok;
420
421 # Process immediate options (possibly exiting)
422 $self->_process_opts;
423
424 # Required options (possibly exiting)
425 $self->_check_required_opts;
426
427 # Setup accessors for options
428 $self->mk_ro_accessors(grep ! /^_/, keys %$self);
429
430 # Setup default alarm handler for alarm($ng->timeout) in plugin
431 $SIG{ALRM} = sub {
432 my $plugin = uc $self->{_attr}->{plugin};
433 $plugin =~ s/^check_//;
434 $self->_die(
435 sprintf("%s UNKNOWN - plugin timed out (timeout %ss)",
436 $plugin, $self->timeout));
437 };
438}
439
440# -------------------------------------------------------------------------
441# Constructor
442
443sub _init
444{
445 my $self = shift;
446
447 # Check params
448 my $plugin = basename($ENV{PLUGIN_NAME} || $ENV{NAGIOS_PLUGIN} || $0);
449 my %attr = validate( @_, {
450 usage => 1,
451 version => 0,
452 url => 0,
453 plugin => { default => $plugin },
454 blurb => 0,
455 extra => 0,
456 'extra-opts' => 0,
457 license => { default => $DEFAULT{license} },
458 timeout => { default => $DEFAULT{timeout} },
459 });
460
461 # Add attr to private _attr hash (except timeout)
462 $self->{timeout} = delete $attr{timeout};
463 $self->{_attr} = { %attr };
464 # Chomp _attr values
465 chomp foreach values %{$self->{_attr}};
466
467 # Setup initial args list
468 $self->{_args} = [ @ARGS ];
469
470 $self
471}
472
473sub new
474{
475 my $class = shift;
476 my $self = bless {}, $class;
477 $self->_init(@_);
478}
479
480# -------------------------------------------------------------------------
481
4821;
483
484__END__
485
486=head1 NAME
487
488Monitoring::Plugin::Getopt - OO perl module providing standardised argument
489processing for Nagios plugins
490
491
492=head1 SYNOPSIS
493
494 use Monitoring::Plugin::Getopt;
495
496 # Instantiate object (usage is mandatory)
497 $ng = Monitoring::Plugin::Getopt->new(
498 usage => "Usage: %s -H <host> -w <warning> -c <critical>",
499 version => '0.1',
500 url => 'http://www.openfusion.com.au/labs/nagios/',
501 blurb => 'This plugin tests various stuff.',
502 );
503
504 # Add argument - named parameters (spec and help are mandatory)
505 $ng->arg(
506 spec => 'critical|c=i',
507 help => q(Exit with CRITICAL status if fewer than INTEGER foobars are free),
508 required => 1,
509 default => 10,
510 );
511
512 # Add argument - positional parameters - arg spec, help text,
513 # default value, required? (first two mandatory)
514 $ng->arg(
515 'warning|w=i',
516 q(Exit with WARNING status if fewer than INTEGER foobars are free),
517 5,
518 1);
519
520 # Parse arguments and process standard ones (e.g. usage, help, version)
521 $ng->getopts;
522
523 # Access arguments using named accessors or or via the generic get()
524 print $ng->warning;
525 print $ng->get('critical');
526
527
528
529=head1 DESCRIPTION
530
531Monitoring::Plugin::Getopt is an OO perl module providing standardised and
532simplified argument processing for Nagios plugins. It implements
533a number of standard arguments itself (--help, --version,
534--usage, --timeout, --verbose, and their short form counterparts),
535produces standardised nagios plugin help output, and allows
536additional arguments to be easily defined.
537
538
539=head2 CONSTRUCTOR
540
541 # Instantiate object (usage is mandatory)
542 $ng = Monitoring::Plugin::Getopt->new(
543 usage => 'Usage: %s --hello',
544 version => '0.01',
545 );
546
547The Monitoring::Plugin::Getopt constructor accepts the following named
548arguments:
549
550=over 4
551
552=item usage (required)
553
554Short usage message used with --usage/-? and with missing required
555arguments, and included in the longer --help output. Can include
556a '%s' sprintf placeholder which will be replaced with the plugin
557name e.g.
558
559 usage => qq(Usage: %s -H <hostname> -p <ports> [-v]),
560
561might be displayed as:
562
563 $ ./check_tcp_range --usage
564 Usage: check_tcp_range -H <hostname> -p <ports> [-v]
565
566=item version (required)
567
568Plugin version number, included in the --version/-V output, and in
569the longer --help output. e.g.
570
571 $ ./check_tcp_range --version
572 check_tcp_range 0.2 [http://www.openfusion.com.au/labs/nagios/]
573
574=item url
575
576URL for info about this plugin, included in the --version/-V output,
577and in the longer --help output (see preceding 'version' example).
578
579=item blurb
580
581Short plugin description, included in the longer --help output
582(see below for an example).
583
584=item license
585
586License text, included in the longer --help output (see below for an
587example). By default, this is set to the standard nagios plugins
588GPL license text:
589
590 This nagios plugin is free software, and comes with ABSOLUTELY
591 NO WARRANTY. It may be used, redistributed and/or modified under
592 the terms of the GNU General Public Licence (see
593 http://www.fsf.org/licensing/licenses/gpl.txt).
594
595Provide your own to replace this text in the help output.
596
597=item extra
598
599Extra text to be appended at the end of the longer --help output.
600
601=item plugin
602
603Plugin name. This defaults to the basename of your plugin, which is
604usually correct, but you can set it explicitly if not.
605
606=item timeout
607
608Timeout period in seconds, overriding the standard timeout default
609(15 seconds).
610
611=back
612
613The full --help output has the following form:
614
615 version string
616
617 license string
618
619 blurb
620
621 usage string
622
623 options list
624
625 extra text
626
627The 'blurb' and 'extra text' sections are omitted if not supplied. For
628example:
629
630 $ ./check_tcp_range -h
631 check_tcp_range 0.2 [http://www.openfusion.com.au/labs/nagios/]
632
633 This nagios plugin is free software, and comes with ABSOLUTELY NO WARRANTY.
634 It may be used, redistributed and/or modified under the terms of the GNU
635 General Public Licence (see http://www.fsf.org/licensing/licenses/gpl.txt).
636
637 This plugin tests arbitrary ranges/sets of tcp ports for a host.
638
639 Usage: check_tcp_range -H <hostname> -p <ports> [-v]
640
641 Options:
642 -h, --help
643 Print detailed help screen
644 -V, --version
645 Print version information
646 -H, --hostname=ADDRESS
647 Host name or IP address
648 -p, --ports=STRING
649 Port numbers to check. Format: comma-separated, colons for ranges,
650 no spaces e.g. 8700:8705,8710:8715,8760
651 -t, --timeout=INTEGER
652 Seconds before plugin times out (default: 15)
653 -v, --verbose
654 Show details for command-line debugging (can repeat up to 3 times)
655
656
657=head2 ARGUMENTS
658
659You can define arguments for your plugin using the arg() method, which
660supports both named and positional arguments. In both cases
661the C<spec> and C<help> arguments are required, while the C<label>,
662C<default>, and C<required> arguments are optional:
663
664 # Define --hello argument (named parameters)
665 $ng->arg(
666 spec => 'hello|h=s',
667 help => "Hello string",
668 required => 1,
669 );
670
671 # Define --hello argument (positional parameters)
672 # Parameter order is 'spec', 'help', 'default', 'required?', 'label'
673 $ng->arg('hello|h=s', "Hello parameter (default %s)", 5, 1);
674
675=over 4
676
677=item spec
678
679The C<spec> argument (the first argument in the positional variant) is a
680L<Getopt::Long> argument specification. See L<Getopt::Long> for the details,
681but basically it is a series of one or more argument names for this argument
682(separated by '|'), suffixed with an '=<type>' indicator if the argument
683takes a value. '=s' indicates a string argument; '=i' indicates an integer
684argument; appending an '@' indicates multiple such arguments are accepted;
685and so on. The following are some examples:
686
687=over 4
688
689=item hello=s
690
691=item hello|h=s
692
693=item ports|port|p=i
694
695=item exclude|X=s@
696
697=item verbose|v+
698
699=back
700
701=item help
702
703The C<help> argument is a string displayed in the --help option list output,
704or it can be a list (an arrayref) of such strings, for multi-line help (see
705below).
706
707The help string is munged in two ways:
708
709=over 4
710
711=item
712
713First, if the help string does NOT begins with a '-' sign, it is prefixed
714by an expanded form of the C<spec> argument. For instance, the following
715hello argument:
716
717 $ng->arg(
718 spec => 'hello|h=s',
719 help => "Hello string",
720 );
721
722would be displayed in the help output as:
723
724 -h, --hello=STRING
725 Hello string
726
727where the '-h, --hello=STRING' part is derived from the spec definition
728(by convention with short args first, then long, then label/type, if any).
729
730=item
731
732Second, if the string contains a '%s' it will be formatted via
733C<sprintf> with the 'default' as the argument i.e.
734
735 sprintf($help, $default)
736
737=back
738
739Multi-line help is useful in cases where an argument can be of different types
740and you want to make this explicit in your help output e.g.
741
742 $ng->arg(
743 spec => 'warning|w=s',
744 help => [
745 'Exit with WARNING status if less than BYTES bytes of disk are free',
746 'Exit with WARNING status if less than PERCENT of disk is free',
747 ],
748 label => [ 'BYTES', 'PERCENT%' ],
749 );
750
751would be displayed in the help output as:
752
753 -w, --warning=BYTES
754 Exit with WARNING status if less than BYTES bytes of disk are free
755 -w, --warning=PERCENT%
756 Exit with WARNING status if less than PERCENT of disk space is free
757
758Note that in this case we've also specified explicit labels in another
759arrayref corresponding to the C<help> one - if this had been omitted
760the types would have defaulted to 'STRING', instead of 'BYTES' and
761'PERCENT%'.
762
763
764=item label
765
766The C<label> argument is a scalar or an arrayref (see 'Multi-line help'
767description above) that overrides the standard type expansion when generating
768help text from the spec definition. By default, C<spec=i> arguments are
769labelled as C<=INTEGER> in the help text, and C<spec=s> arguments are labelled
770as C<=STRING>. By supplying your own C<label> argument you can override these
771standard 'INTEGER' and 'STRING' designations.
772
773For multi-line help, you can supply an ordered list (arrayref) of labels to
774match the list of help strings e.g.
775
776 label => [ 'BYTES', 'PERCENT%' ]
777
778Any labels that are left as undef (or just omitted, if trailing) will just
779use the default 'INTEGER' or 'STRING' designations e.g.
780
781 label => [ undef, 'PERCENT%' ]
782
783
784=item default
785
786The C<default> argument is the default value to be given to this parameter
787if none is explicitly supplied.
788
789
790=item required
791
792The C<required> argument is a boolean used to indicate that this argument
793is mandatory (Monitoring::Plugin::Getopt will exit with your usage message and
794a 'Missing argument' indicator if any required arguments are not supplied).
795
796=back
797
798Note that --help lists your arguments in the order they are defined, so
799you should order your C<arg()> calls accordingly.
800
801
802=head2 GETOPTS
803
804The main parsing and processing functionality is provided by the getopts()
805method, which takes no arguments:
806
807 # Parse and process arguments
808 $ng->getopts;
809
810This parses the command line arguments passed to your plugin using
811Getopt::Long and the builtin and provided argument specifications.
812Flags and argument values are recorded within the object, and can
813be accessed either using the generic get() accessor, or using named
814accessors corresponding to your argument names. For example:
815
816 print $ng->get('hello');
817 print $ng->hello();
818
819 if ($ng->verbose) {
820 # ...
821 }
822
823 if ($ng->get('ports') =~ m/:/) {
824 # ...
825 }
826
827Note that where you have defined alternate argument names, the first is
828considered the citation form. All the builtin arguments are available
829using their long variant names.
830
831
832=head2 BUILTIN PROCESSING
833
834The C<getopts()> method also handles processing of the immediate builtin
835arguments, namely --usage, --version, --help, as well as checking all
836required arguments have been supplied, so you don't have to handle
837those yourself. This means that your plugin will exit from the getopts()
838call in these cases - if you want to catch that you can run getopts()
839within an eval{}.
840
841C<getopts()> also sets up a default ALRM timeout handler so you can use an
842
843 alarm $ng->timeout;
844
845around any blocking operations within your plugin (which you are free
846to override if you want to use a custom timeout message).
847
848
849=head1 SEE ALSO
850
851Monitoring::Plugin, Getopt::Long
852
853
854=head1 AUTHOR
855
856This code is maintained by the Monitoring Plugin Development Team: see
857https://monitoring-plugins.org
858
859Originally:
860 Gavin Carr <gavin@openfusion.com.au>
861
862=head1 COPYRIGHT AND LICENSE
863
864Copyright (C) 2006-2014 Monitoring Plugin Development Team
865
866This library is free software; you can redistribute it and/or modify
867it under the same terms as Perl itself.
868
869=cut