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