Icinga 2 command definitions can seem daunting at first. This blog post provides a quick introduction to some of the concepts you need to be familiar with when writing your own command definitions.

In their most basic form command definitions need a command line:

object CheckCommand "my_http" {
  import "plugin-check-command"

  command = [ PluginDir + "/check_http" ]

The “plugin-check-command” template tells Icinga how to execute commands, i.e. by executing an external plugin. There are a few other “*-check-command” templates but for virtually all of your own check commands you’ll need to use “plugin-check-command”.

The check_http plugin needs at least one more argument to work:

$ /opt/local/libexec/nagios/check_http -I
HTTP OK: HTTP/1.1 200 OK - 342 bytes in 0.001 second response time |time=0.001344s;;;0.000000 size=342B;;;0

We can add this argument to our check command like this:

object CheckCommand "my_http" {
  import "plugin-check-command"

  command = [ PluginDir + "/check_http" ]

  arguments = {
    "-I" = {
      value = "$my_http_address$"
      description = "IP address or name."
      required = true

  vars.my_http_address = "$address$"

The ‘required’ option tells Icinga to verify that the user specified a value for this argument.

We’re prefixing our custom attributes (my_http_address) with the name of the CheckCommand. This allows us to override specific custom attributes for HTTP checks on a per-host or per-service basis. If all
commands had the same custom attribute names (e.g. ‘timeout’) this wouldn’t be possible:

object Host "test" {

  // This affects all services on this host which use the my_http command
  vars.my_http_address = ""

In our next step we’re going to add a few optional arguments. The check_http plugin lets us specify the ‘Host’ header and the URL that should be used. Adding optional arguments is rather simple:

    "-H" = {
      value = "$my_http_vhost$"
      description = "Host name argument for servers using host headers"
    "-u" = {
      value = "$my_http_url$"
      description = "URL to GET or POST (default: /)"

When Icinga encounters a command argument which uses an unresolvable macro (for example, because the user didn’t set a value for vars.my_http_vhost in their command, service or host) the entire argument is omitted.

Icinga can also add arguments only when certain conditions are met. In the next example I’m adding a new option ‘–sni’ which is only added when the custom attribute my_http_sni is set to true:

    "--sni" = {
      description = "Enable SSL/TLS hostname extension support (SNI)"
      set_if = "$my_http_sni$"

Note that the ‘–sni’ option does not take an argument. Therefore we don’t need the ‘value’ attribute for this argument.

When the ‘my_http_sni’ custom attribute isn’t set at all Icinga defaults to not adding the argument.

There are a few more advanced topics for command arguments which aren’t covered in this blog post:

  • Ordering arguments
  • Using arrays for custom variables (with repeat_key/skip_key)
  • Using functions for set_if/value
  • Specifying an alternative ‘key’

I might write another blog post at a later point in time which deals with those features. In the meantime these things are explained in the documentation.