Nagios Plugins
Development Guidelines
Reference guide for Nagios plugin developers to ensure standardization across C, shell, Perl, Python, and other plugin types.
Preface
The purpose of these guidelines is to provide a reference for plugin developers and encourage standardization of different kinds of plugins: C, shell, Perl, Python, etc.
Copyright (C) 2000– Nagios Plugins Team. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Development Platform Requirements
Nagios Plugins are developed to the GNU standard, so any OS supported by GNU should run the plugins. While the requirements for compiling the Nagios Plugins release are basic, developing from the Git repository requires additional software:
- GNU make 3.79
- GNU automake 1.9.2
- GNU autoconf 2.59
- GNU m4 1.4.2
- GNU libtool 1.5
To compile from Git, after cloning the repository, run:
cd tools/setup
./configure
make
make install
Plugin Output for Nagios
Always print something to STDOUT that tells if the service is working or why it's failing. Keep output short—ideally less than 80 characters. The entire output should fit in a pager message.
As Nagios does not capture stderr output, you should only output to STDOUT and not print to STDERR.
Verbose Output
Use the -v flag for verbose output. Allow multiple -v options for additional verbosity, up to a maximum of 3:
| Verbosity Level | Type of Output |
|---|---|
| 0 | Single line, minimal output. Summary |
| 1 | Single line, additional information (eg list processes that fail) |
| 2 | Multi line, configuration debug output (eg ps command used) |
| 3 | Lots of detail for plugin problem diagnosis |
Plugin Return Codes
Return codes are based on the POSIX spec of returning a positive value:
| Numeric Value | Service Status | Status Description |
|---|---|---|
| 0 | OK | The plugin was able to check the service and it appeared to be functioning properly |
| 1 | Warning | The plugin was able to check the service, but it appeared to be above some "warning" threshold or did not appear to be working properly |
| 2 | Critical | The plugin detected that either the service was not running or it was above some "critical" threshold |
| 3 | Unknown | Invalid command line arguments were supplied to the plugin or low-level failures internal to the plugin that prevent it from performing the specified operation |
Threshold and Ranges
A range is defined as a start and end point (inclusive) on a numeric scale. A threshold is a range with an alert level (warning or critical).
Generalized format for ranges: [@]start:end
Notes:
- start ≤ end
- start and ":" is not required if start=0
- if range is "start:" and end is not specified, assume end is infinity
- to specify negative infinity, use "~"
- alert is raised if metric is outside start and end range (inclusive)
- if range starts with "@", then alert if inside this range (inclusive)
Example Ranges
| Range Definition | Generate an Alert if x... |
|---|---|
| 10 | < 0 or > 10, (outside the range of {0 .. 10}) |
| 10: | < 10, (outside {10 .. ∞}) |
| ~:10 | > 10, (outside the range of {-∞ .. 10}) |
| 10:20 | < 10 or > 20, (outside the range of {10 .. 20}) |
| @10:20 | ≥ 10 and ≤ 20, (inside the range of {10 .. 20}) |
Command Line Examples
| Command Line | Meaning |
|---|---|
check_stuff -w10 -c20 |
Critical if "stuff" is over 20, else warn if over 10 |
check_stuff -w~:10 -c~:20 |
Same as above. Negative "stuff" is OK |
check_stuff -w10: -c20 |
Critical if "stuff" is over 20, else warn if "stuff" is below 10 |
check_stuff -c1: |
Critical if "stuff" is less than 1 |
check_stuff -c@10:20 |
OK if stuff is less than 10 or higher than 20, otherwise critical |
Performance Data
Nagios 3+ will concatenate the parts following a "|" in the first line output by the plugin into a string it passes to whatever performance data processing it has configured.
Expected format:
'label'=value[UOM];[warn];[crit];[min];[max]
Notes:
- Space separated list of label/value pairs
- Label can contain any characters except equals sign or single quote (')
- Single quotes for the label are optional (required if spaces are in the label)
- Label length is arbitrary, but ideally first 19 characters are unique
- warn, crit, min or max may be null
- min and max are not required if UOM=%
- value, min and max in class [-0-9.]. Must all be the same UOM
- UOM (unit of measurement): no unit (numbers), s (seconds), % (percentage), B (bytes), c (continuous counter)
System Commands and Auxiliary Files
Don't Execute System Commands Without Full Path
Don't use exec(), popen(), etc. to execute external commands without explicitly using the full path. This makes the plugin vulnerable to hijacking by a trojan horse earlier in the search path.
Use spopen() for External Commands
If you have to execute external commands from within your plugin and you're writing it in C, use the spopen() function. The code for spopen() and spclose() is included with the core plugin distribution.
Avoid Temporary Files
If temp files are needed, ensure the plugin fails cleanly if the file can't be written and delete the temp file when processing is complete.
Don't Follow Symlinks
If your plugin opens any files, take steps to ensure you are not following a symlink to another location on the system.
Validate All Input
Use routines in utils.c or utils.pm and write more as needed.
Perl Plugins
Perl plugins are coded more defensively because of embedded Perl. When configured for embedded Perl Nagios (ePN), stricter use of Perl features is required:
- Do not use BEGIN and END blocks—they're called only once when Nagios starts/shuts down
- Provide full path to utils.pm:
use lib "/usr/local/nagios/libexec"; use utils qw(...); - Perl scripts should be called with "-w"
- All Perl plugins must compile cleanly under "use strict"
- Explicitly initialize each variable in use
- Do not use >DATA< handles
- Do not use global variables in named subroutines
- Explicitly close files when writing (output streams are never closed as plugin never calls exit)
- Monitor runtime using alarm, noting some modules manage timers
- Import %ERRORS from utils.pm and use
exit $ERRORS{'OK'}
Runtime Timeouts
Plugins have a very limited runtime—typically 10 seconds. It's important for plugins to maintain internal code to exit if runtime exceeds a threshold.
All plugins should timeout gracefully, not just networking plugins. For instance, df may lock if you have auto-mounted drives and your network fails.
Use DEFAULT_SOCKET_TIMEOUT
All network plugins should use DEFAULT_SOCKET_TIMEOUT to timeout.
Add Alarms to Network Plugins
If you write a plugin which communicates with another networked host, set an alarm() in your code that prevents the plugin from hanging due to abnormal socket closures.
Plugin Options
A well written plugin should have --help to get verbose help. Code and output should respect the 80x25 size of a standard terminal.
Option Processing
For C plugins, use the C standard getopt library. For Perl, use Getopt::Long module. Positional arguments are strongly discouraged.
Reserved Options
-V version (--version)
-h help (--help)
-t timeout (--timeout)
-w warning threshold (--warning)
-c critical threshold (--critical)
-H hostname (--hostname)
-v verbose (--verbose)
Standard Options
-C SNMP community (--community)
-a authentication password (--authentication)
-l login name (--logname)
-p port or password (--port or --passwd/--password)
-u url or username (--url or --username)
Multiple Thresholds
For plugins with more than one type of threshold:
- Use long options like
--critical-time - Use repeated options:
check_load -w 10 -w 6 -w 4 -c 16 -c 10 -c 10 - Use comma-separated values:
check_load -w 10,6,4 -c 16,10,10 - Express ranges with colons:
check_procs -C httpd -w 1:20 -c 1:30 - Express lists with commas:
-p 1000,1010,1050:1060,2000
Test Cases
Tests are the best way of knowing if plugins work as expected. Please create and update test cases where possible.
To run tests from the top level directory: make test
Test Cases for Plugins
These use Perl's Test::More. To run a one-time test:
cd plugins && perl t/check_disk.t
For a summary test:
cd plugins && prove t/check_disk.t
Testing C Library Functions
We use the libtap library, which gives Perl's TAP (Test Anything Protocol) output. When you run Nagios Plugins' configure, it will look for the tap library and automatically setup tests.
Coding Guidelines
See GNU Coding Standards for general guidelines.
C Coding
- Declare variables at the beginning of code blocks for portability
- Use
/* */for comments, not// - Avoid type "bool" and values "true"/"false"—use "int" and "TRUE"/"FALSE"
Crediting Sources
If you've copied a routine from another source, ensure the license allows it. Add a comment referencing the ACKNOWLEDGEMENTS file. For contributed code, add contributors to the THANKS.in file instead of source code.
Commit Messages
If the change is due to a contribution, quote the contributor's name and SourceForge Tracker number if applicable. Update the THANKS.in file and NEWS file for changes useful for noting in the next release.
Translations
For Developers
- Check po/nagios-plugins.pot file for similar strings before creating new ones
- Break help texts into individual options for reuse between plugins
- Avoid line feeds unless working on a block of text
- Short help is not translated
- Long help has options in English but text translated
- Keep "Copyright" in English
- Keep copyright holder names in original text
- Debugging output doesn't need translation
For Translators
To create an up-to-date list of translatable strings, run:
tools/gen_locale.sh
Submission of New Plugins and Patches
Patches
For bug patches, supply a unified or context diff against your version. For new features, supply a diff against the Git "master" branch.
Submit changes and pull requests via the Nagios-Plugins project on GitHub.
Submission of a patch implies the submitter acknowledges they are the author (or have permission) and agree the code can be released under the GPL. Copyright reverts to the Nagios Plugin Development Team. Credit is given through a THANKS file.
Contributed Plugins
Plugins in the contrib/ directory are not installed by default and not officially supported by the team. These should be owned and maintained by the original contributor, preferably hosted on Nagios Exchange.
New Plugins
To share your plugins with others, add them to Nagios Exchange, the official 3rd party plugin repository.
Minimum requirements for inclusion in official distribution:
- Include copyright and license information in all files. Copyright must be solely granted to the Nagios Plugin Development Team
- Support standard command options (
--help,--version,--timeout,--warning,--critical) - Not redundant with existing plugins
- Audited and declared ready by a developer
- Follow code format guidelines and use functions from utils
- Include patches to configure.in if required
Docs