Plugin:Exec

From collectd Wiki

Jump to: navigation, search
Exec plugin
Type: other
Callbacks: config, init, notification, read, shutdown
Status: supported
First version: 4.0
Copyright: 2007–2010 Florian “octo” Forster
2007–2009 Sebastian Harl
2008 Peter Holik
License: GPLv2
Manpage: collectd.conf(5)
collectd-exec(5)
List of Plugins

Contents

Description

The Exec plugin executes scripts / applications and reads values back that are printed to STDOUT by that program. This allows you to extend the daemon in an easy and flexible way.

The downside is that executing external programs is very inefficient and always a potential security concern. collectd tries to counter these problems with the following options / mechanism:

It is ensured, that only one instance of the program is executed by collectd at any time. Because executed programs can submit as many values as they want, it is common to let the custom program run in a loop, so that they don't have to be started frequently. Especially with scripts this is a big performance gain, because the interpreter doesn't need to be started over and over again and the script is parsed only once. The required memory for the interpreter to stay in memory is the trade-off though.

Scripts that are implemented like that usually have the following form:

 HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
 INTERVAL="${COLLECTD_INTERVAL:-60}"
 
 while sleep "$INTERVAL"; do
   VALUE=do_magic()
   echo "PUTVAL \"$HOSTNAME/exec-magic/gauge-magic_level\" interval=$INTERVAL N:$VALUE"
 done

The security concerns are addressed by forcing the plugin to check that custom programs are never executed with superuser privileges. If the daemon runs as root, you have to configure another user ID with which the new process is created.

This plugin is a generic plugin, i.e. it cannot work without configuration, because there is no reasonable default behavior. Please read the Plugin exec section of the collectd.conf(5) manual page for an in-depth description of the plugin's configuration. Information about the syntax the custom extension scripts must write to STDOUT can be found in the collectd-exec(5) manual page and on the Plain text protocol wiki page.

Environment

Starting with version 4.9 the Exec plugin sets the COLLECTD_INTERVAL and COLLECTD_HOSTNAME environment variables. The former is set to the global interval setting, the latter to the global hostname.

Synopsis

<Plugin exec>
  Exec "myuser:mygroup" "myprog"
  Exec "otheruser" "/path/to/another/binary" "arg0" "arg1"
  NotificationExec "user" "/usr/lib/collectd/exec/handle_notification"
</Plugin>

Example graph

Image:Plugin-exec-temperature-3ware.png

(Data for this graph was collected using the contrib/exec-smartctl script which can be found in contrib/.)

Example scripts

While the syntax required by the Exec plugin is documented in detail on the Plain text protocol page, example scripts are usually much easier to understand. The following scripts might be of interest for you:

Dependencies

  • none

Caveats

Output buffering

A lot of programming environments (I/O-libraries, script interpreters) use buffered I/O when writing to the standard output. This may mean that data you're printing to the collectd process may be delayed until a 4 kByte buffer gets filled (or something around that size), which can be several minutes later.

To avoid this problem is it advisable to flush this buffer before calling sleep. Many environments also provide means to disable buffering, for example the following will deactivate buffering on stdout using the standard C library:

 /* This needs to be done before *anything* is written to STDOUT! */
 status = setvbuf (stdout,
     /* buf  = */ NULL,
     /* mode = */ _IONBF, /* unbuffered */
     /* size = */ 0);
 if (status != 0)
 {
   perror ("setvbuf");
   exit (EXIT_FAILURE);
 }

This Perl snipped will enable automatic flushing after each write:

 # Enable auto flush
 $| = 1;

In Ruby you'd do something like:

 # Enable auto flush
 STDOUT.sync = true

Heads up: While this behavior is merely confusing when you include timestamps in your messages, it may lead to invalid value lists if you use the N (now) abbreviation: Since the time is only filled in when collectd receives the values, it may be several minutes late. If the same identifier is contained in the buffer multiple times, all values will bear the same time stamp and all but the first value will be lost.

Heads up 2: The stdout macro, which is specified by POSIX and used by many environments as the underlying I/O mechanism, behaves differently when connected to a terminal and to a pipe: When connected to a terminal, the output is "line buffered", i.e. the buffer is flushed when a newline is printed. When connected to a pipe, the stream is "fully buffered", i.e. output is only actually written if a fixed size buffer is full. This means that the output can actually appear immediately when testing the code in the command line, but still suffer from the problem when actually running with collectd.

See also