A Ruby DSL for writing Nagios plugins. It handles the tedium of argument parsing, exit statuses, output formatting and such, and lets you focus on writing the actual check.
Written by Erik Grinaker <[email protected]>, and licensed under the GNU GPL v3.
A very simple plugin looks like this:
#!/usr/bin/env ruby
require 'nagi'
Nagi do
name 'check_true'
version '0.1'
prefix 'TRUE'
check do |args|
if true
ok 'True is still true'
else
critical 'Uh oh'
end
end
end
The first few methods just set some basic info for the plugin - the name, version, and a prefix for the check output. These are all optional.
Next, the check block is defined, which runs the actual Nagios check. args
will contains any options (see command-line parsing below), and the methods ok,
warning, critical, and unknown are used to return the check status. A missing
status or uncaught exception will result in an 'unknown' status.
The plugin is run as any regular script - save it as a file, make it executable and run it:
$ ./test.rb
TRUE OK: True is still true
Nagi can automatically parse command-line arguments when requested, and provide them as input to the check block. Here is a simple example:
#!/usr/bin/env ruby
require 'nagi'
require 'resolv'
Nagi do
name 'check_dns'
version '0.1'
prefix 'DNS'
argument :hostname
switch :ip, '-i', '--ip IP', 'Expected IP address'
check do |args|
begin
ip = Resolv.getaddress(args[:hostname])
rescue Resolv::ResolvError => e
critical e.message
end
if args[:ip] and ip != args[:ip]
critical "#{args[:hostname]} resolves to #{ip}, expected #{args[:ip]}"
else
ok "#{args[:hostname]} resolves to #{ip}"
end
end
end
The argument
method specifies a required positional argument, and only takes
the name of the argument. switch
specifies an optional switch, which may or
may not take an argument of its own. The first switch
parameter is its name,
while the rest are passed to the standard Ruby OptionParser.on method - see its
documentation for details.
The parsed arguments are passed to the check
block via the args
parameter,
which is a hash containing argument names and values. In the case of a switch
with no argument of its own, the value will be true
.
A few usage examples of this plugin:
$ ./check_dns.rb
Error: Argument 'hostname' not given
Usage: ./check_dns.rb [options] <hostname>
-i, --ip IP Expected IP address
-h, --help Display this help message
-V, --version Display version information
$ ./check_dns.rb www.google.com
DNS OK: www.google.com resolves to 173.194.35.148
$ ./check_dns.rb -i 1.2.3.4 www.google.com
DNS CRITICAL: www.google.com resolves to 173.194.35.148, expected 1.2.3.4
Nagi will automatically set up the -h/--help and -V/--version switches and handle them appropriately.
In some cases it is useful to collect several statuses and return the most severe, rather than returning the first status encountered. This is typically used when monitoring multiple resources with a single check.
The collect
setting tells Nagi to continue running the check when a status
is given. It can be set to either :severe
, in which case the most severe
status will be returned at the end, or :all
which will use the most severe
status code but also combine all status messages into one.
However, one can still force a status to return from the check, and ignore
the collected statues, by setting the second parameter (force
) to true
for the status methods.
This example checks used space on all disk drives, and returns critical if any of the drives are above a threshold:
#!/usr/bin/env ruby
require 'nagi'
Nagi do
name 'check_df'
version '0.1'
prefix 'DF'
argument :percentage
collect :all
check do |args|
begin
output = execute 'df'
rescue StandardError => e
critical "df failed: #{e.message}", true
end
output.lines.each do |line|
if line =~ /^.*?(\d+)%\s*(.*)$/
if $1.to_i > args[:percentage].to_i
critical "#{$2} #{$1}% used"
else
ok "#{$2} #{$1}% used"
end
end
end
end
end
When run, it will output something like this:
$ ./check_df.rb 90
DF OK: / 80% used, /Volumes/Media 57% used
$ ./check_df.rb 70
DF CRITICAL: / 80% used, /Volumes/Media 57% used
These describe the program, and are usually given first, if necessary.
name
name: the program name.version
version: the program version.prefix
prefix: a prefix for the check output.collect
type: collect statuses and continue the check, rather than returning. type can be either:severe
or:all
-:severe
will return the last, most severe status, and:all
will use the most severe status but join all the status messages together into one.fallback
status, message: a default status to return if the check doesn't explicitly return one. status can be:ok
,:warning
,:critical
, or:unknown
.
Command-line arguments can be specified, and will be parsed automatically and
passed to the check
method as a hash, with keys given by the argument name.
argument
name: a mandatory, positional argument.switch
name, args: an optional switch. args are passed directory to the standard Ruby OptionParser class - see its documentation for details.
Command-line arguments for -h/--help and -V/--version are added and handled automatically.
The check is given as a code block to the check
method, and is passed the
parsed command-line arguments as a hash. It should use one of the methods ok
,
warning
, critical
, or unknown
to return a status. If no status is given,
or the block raises an unhandled exception, an Unknown status will be returned.
The collect
setting (see above) can be used to collect statuses and continue
the check, rather than returning the first status encountered. However, if
true
is passed as the second parameter of the status method, it will
return the status regardless of the collect
setting.
check
block: the code block the the check. Parsed command-line arguments are passed as a hash.ok
message, force=false: returns an OK status.warning
message, force=false: returns a Warning status.critical
message, force=false: returns a Critical status.unknown
message, force=false: returns an Unknown status.execute
command: executes a shell command, and returns any output (both stdout and stderr). If the command exits with a non-zero status, it will throw an exception. The shell is set to use thepipefail
option, so non-zero exit statuses in pipelines are detected as well.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.