Skip to content

Legacy exec plugins

Twenty years of Nagios plugins exist — check_mk agents, vendor scripts, that one Perl thing a former colleague wrote in 2009. jaque runs all of them, unmodified, and commits to doing so forever.

A legacy check executes a plugin binary and interprets its output the way Nagios always has:

  • Exit code 0/1/2/3 maps directly to OK/WARNING/CRITICAL/UNKNOWN.
  • Stdout is the check output; a | splits it into text and perfdata, same convention as everywhere else.
services: disk: check: {
type: "legacy"
path: "/usr/lib/nagios/plugins/check_disk"
args: ["-w", "20%", "-c", "10%", "-p", "/"]
}

The text after | is parsed as zero or more space-separated metrics, each of the form:

label=value[UOM];warn;crit;min;max
  • label is everything before the first =, unless it starts with a single quote ('), in which case it runs to the next unescaped ' and may contain spaces — a doubled '' inside a quoted label is a literal quote, not a close. Space inside an unquoted label is not supported: it would end the token early.
  • value is a plain int or float, optionally signed and with an exponent (1, -0.5, 1e3), immediately followed by an optional UOM made only of letters, %, and / — a token whose unit contains anything else fails to parse.
  • ;warn;crit;min;max are semicolon-separated and optional from the right: label=value alone is valid, and so is label=value;warn, label=value;warn;crit, and so on up to all four. warn and crit are Nagios threshold range specs (see exec.Threshold); min and max are plain floats. A token with more than five ;-separated fields fails to parse.
  • Multiple metrics are separated by whitespace outside quoted labels; a malformed token is dropped without failing the metrics around it.
time=0.125s;1.0;2.0;0;5 'packet loss'=0%;20;40

Each execution runs in its own process group. On timeout, jaque kills the whole group, not just the immediate child — a plugin that forks a helper and hangs doesn’t leave an orphan behind. timeout is per-check (defaulting to 10s from #Schedule), and a timed-out or otherwise unrunnable plugin (wrong path, not executable, killed by signal) is reported as an honest UNKNOWN rather than silently retried into a false OK.

This is a firm commitment: legacy exec support is not a migration aid you’re expected to outgrow. Vendor plugins, internal tooling, anything speaking the exit-code protocol keeps working indefinitely — the same posture as WASM checks for anything you’d rather sandbox and distribute as a single file instead.