ZabbixPipe

2nd July 2015 at 9:40am
Bash CodeSnippets Zabbix

This is a quick and dirty script (a bash daemon no less... ahem), that will create a named pipe (/var/zabbix/zabbix_piped/zabbix_piped.pipe), and forward key value pair metrics to your Zabbix server for ingestion as "Zabbix Trapper" data items.

Think of it as /dev/log, but instead of for syslog, for Zabbix.

Start the daemon:

nicolaw@nicolaw:~ $ ./zabbix_piped
Forked zabbix_piped background daemon at PID 16638 using input pipe '/var/run/zabbix/zabbix_piped/zabbix_piped.pipe'.

... then send stuff to the named pipe:

nicolaw@nicolaw:~ $ perl -e '$| = 1; $i = 1; while ($i++) { print ("- test.foo.eng.key1 ".time()." ".((sin($i * 0.1) * 10)+10) ."\n"); sleep 5;}' > /tmp/zabbix.pipe

or

echo "key value" > /tmp/zabbix.pipe

The daemon code:

#!/bin/bash

PROG="${0##*/}"
RUNDIR="/var/run/zabbix/$PROG"
PIPE="$RUNDIR/$PROG.pipe"
CONF="/etc/zabbix/zabbix_agentd.conf"
PIDFILE="$RUNDIR/$PROG.pid"
WAITSECS=30
SENDER="/usr/bin/zabbix_sender"

if [ -e "$PIDFILE" ] ; then
    OTHERPID="$(head -n 1 "$PIDFILE")"
    if [ "$?" != "0" ] ; then
      echo "Lock failed; failed to read PID file '$PIDFILE'." >&2
      exit 3
    fi
    if [ -n "$OTHERPID" ] ; then
        if [ -d "/proc/$OTHERPID" ] ; then
            echo "Lock failed; PID $OTHERPID is active." >&2
            exit 3
        else
            echo "Removing stale lock of non-existant PID $OTHERPID." >&2
            rm -rf --one-file-system "$RUNDIR"
            unset OTHERPID
        fi
    fi
fi

if mkdir -p "$RUNDIR" &>/dev/null ; then
    trap 'rm -rf --one-file-system "$RUNDIR"' EXIT
    echo "$$" > "$PIDFILE"
    trap 'echo "Killed by a signal." >&2; exit 4' SIGHUP SIGINT SIGQUIT SIGTERM
else
    echo "Lock failed; failed to create run directory '$RUNDIR/'." >&2
    exit 3
fi

SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SELF_FILE=$(basename $0)
cd /

if [ "$1" = "child" ] ; then
    shift
    umask 0
    exec setsid $SELF_DIR/$SELF_FILE refork "$@" </dev/null >/dev/null 2>/dev/null &
    CHILDPID="$!"
    echo "$CHILDPID" > "$PIDFILE"
    echo "Forked $PROG background daemon at PID $CHILDPID using input pipe" \
         "'$PIPE'."
    exit 0
fi
if [ "$1" != "refork" ] ; then
    exec $SELF_DIR/$SELF_FILE child "$@" &
    exit 0
fi

shift

exec >  >(2>&-; logger -t "$PROG[$$]" -p user.info 2>&1)
exec 2> >(      logger -t "$PROG[$$]" -p user.error    )
exec 0< /dev/null

echo "Forked $PROG background daemon at PID $$."

while : ; do
    if [[ ! -p "$PIPE" ]]; then
        echo "Creating pipe '$PIPE' ..."
        mkfifo "$PIPE"
    fi

    echo "Starting read loop for pipe '$PIPE' ..."
    while : ; do
        if read line < "$PIPE" ; then
            col=( $line )
            case ${#col[@]} in
                4)
                    echo "${col[@]}" >&2
                    echo "${col[@]}"
                    ;;
                2)
                    timestamp="$(date +%s)"
                    echo "- ${col[0]} $timestamp ${col[1]}" >&2
                    echo "- ${col[0]} $timestamp ${col[1]}"
                    ;;
                *)
                    echo "Ignoring invalid input: ${col[@]}" >&2
                    ;;
            esac
        fi
    done | "$SENDER" -c "$CONF" -s "$(hostname -f)" -T -i - -r

    >&2 echo "$SENDER exited with exit code $?; waiting $WAIT seconds."
    sleep $WAIT
done