Ad Widget

Collapse

Simple dashboard using bash, wget and the JSON API

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ximon18
    Junior Member
    • Oct 2010
    • 1

    #1

    Simple dashboard using bash, wget and the JSON API

    Hi there,



    This screenshot was taken from a HTML page generated by the following script:

    Code:
    #!/bin/bash
    # Ximon Eighteen 2010-10-11
    # This script uses wget to query via HTTP POST calls the Zabbix JSON API for
    # status information which it then uses to generate a simple HTML report on
    # STDOUT. User www-data runs this script from its crontab once a minute and
    # saves the output in /data/www/default/pages/status.html. The index.php page
    # then includes status.html in an <iframe> tag.
    
    ZABBIX_HOST='127.0.0.1'
    ZABBIX_USER='Dashboard User'
    ZABBIX_PASS='dash'
    TICK_URL="/images/tick.png"
    CROSS_URL="/images/cross.png"
    
    # an array of Zabbix items to check.
    # format: our display name=zabbix item id=expected trigger status
    ZABBIX_ITEMS[1]="Linux Server 1=22297=0"
    ZABBIX_ITEMS[2]="Linux Server 2=22447=0"
    ZABBIX_ITEMS[3]="XP Virtual Machine=22541=0"
    ZABBIX_ITEMS[4]="Blah blah=22380=1"
    ZABBIX_ITEMS[5]="Confluence=22375=1"
    ZABBIX_ITEMS[6]="Hudson=22379=1"
    ZABBIX_ITEMS[7]="Jira=22376=1"
    ZABBIX_ITEMS[8]="Nexus=22378=1"
    ZABBIX_ITEMS[9]="Sharepoint=22415=1"
    ZABBIX_ITEMS[10]="Subversion=22377=1"
    
    # authenticate: provide the username and password to Zabbix via the JSON API
    #   - use wget to make the API call
    #   - send wget stderr to stdout because wget prints the response headers to
    #     stderr, including the Set-Cookie line we are interested in
    #   - use grep to capture the Set-Cookie line
    #   - for some reason we get multiple Set-Cookie response lines so use the head
    #     command to just take the first
    #   - use the cut command to capture just the cookie value from the line
    # returns the auth token to use on subsequent requests
    authenticate() {
            wget -q -S -O/dev/null http://$ZABBIX_HOST/zabbix/api_jsonrpc.php --header 'Content-Type: application/json-rpc' --post-data "{\"auth\":null,\"method\":\"user.authenticate\",\"id\":0,\"params\":{\"password\":\"$ZABBIX_PASS\",\"user\":\"$ZABBIX_USER\"},\"jsonrpc\":\"2.0\"}" 2>&1 | grep -Eo 'Set-Cookie: zbx_sessionid=.+' | head -n 1 | cut -d '=' -f 2
    }
    
    begin_html() {
            cat <<EOF
    <html>
    <head>
      <style type="text/css">
        body { font-family: courier; font-size: 14pt; }
        td {
          font-family: helvetica;
          font-size: 22px;
          padding-right: 10px;
          vertical-align: middle;
          text-align: left;
        }
        img { height: 20px; }
      </style>
    </head>
    <body>
    <p>Status Report:</p>
    <table border="0">
    EOF
    }
    
    end_html() {
            NOW=$(date +'%F %d %Y %H:%M:%S')
            cat <<EOF
    </table>
    <p>$NOW</p>
    </body>
    </html>
    EOF
    }
    
    # for each Zabbix item query its status via the JSON API
    # i'm sure that if I understood the Zabbix JSON API better this would be easier
    render_item_statuses() {
            AUTH_TOKEN=$1
            API_URL=http://$ZABBIX_HOST/zabbix/api_jsonrpc.php
            HTTP_HEADERS='Content-Type: application/json-rpc'
            POST_DATA_TEMPLATE="{\"auth\":\"$AUTH_TOKEN\",\"method\":\"item.get\",\"id\":4,\"params\":{\"extendoutput\":true,\"itemids\":<ITEMID>,\"filter\":\"lastvalue\",\"limit\":100},\"jsonrpc\":\"2.0\"}"
            WGET_CMD_TEMPLATE="wget -q -O- $API_URL --header '$HTTP_HEADERS' --post-data '<POSTDATA>'"
    
            for TRIO in "${ZABBIX_ITEMS[@]}"; do
                    # split at the equals sign
                    HOST_NAME=$(echo $TRIO | cut -d '=' -f 1)
                    ITEM_ID=$(echo $TRIO | cut -d '=' -f 2)
                    EXPECTED_STATUS=$(echo $TRIO | cut -d '=' -f 3)
    
                    # prepare the HTTP POST data
                    POST_DATA=$(echo "$POST_DATA_TEMPLATE" | sed -e "s/<ITEMID>/$ITEM_ID/")
    
                    # prepare the command to execute
                    WGET_CMD=$(echo "$WGET_CMD_TEMPLATE" | sed -e "s/<POSTDATA>/$POST_DATA/")
    
                    # obtain the status by parsing API output
                    STATUS=$(eval $WGET_CMD | grep -Eo '"lastvalue":"[0-9]"' | cut -d '"' -f 4)
    
                    # generate a line of HTML for this item
                    echo -n "<tr><td>$HOST_NAME</td><td>"
                    if [ "$STATUS" -eq "$EXPECTED_STATUS" ]; then
                            echo -n "<img src=\"$TICK_URL\">"
                    else
                            echo -n "<img src=\"$CROSS_URL\">"
                    fi
                    echo "</td></tr>"
            done
    }
    
    AUTH_TOKEN=$(authenticate)
    begin_html
    render_item_statuses $AUTH_TOKEN
    end_html
    I'm not saying it's pretty, but it works. I thought it might help someone else create a simple dashboard based on Zabbix items. The user that connects to Zabbix needs to have API access enabled and (probably) needs to have read access to the hosts whose items are being queried. The script doesn't handle failure at all, it expects to be able to talk to Zabbix and get the expected output from it. It was tested against Zabbix 1.8.1 on Ubuntu Linux 10.04.1 LTS, wget 1.12, cut 7.4, bash 4.1.5(1), and grep 2.5.4.

    You'll need to provide your own tick and cross images.

    The API URLs and POST data were obtained by trying to query things with ZabCon (and failing, I couldn't work out how to get a specific item state) and monitoring its activity using Wireshark

    Hope it helps someone.

    Cheers,

    Ximon
  • mjsr
    Junior Member
    • Feb 2011
    • 15

    #2
    Ximon, even tho this is a late reply, I'd wanted to thank you for the nice piece of code there.

    Thanks!

    Comment

    • cloudmafia
      Junior Member
      • Nov 2012
      • 23

      #3
      Looks pretty...can someone work on it to make it better...Dashboard is most important part in monitoring...it will be very nice if someone can work on dashboard...

      Thanks

      Comment

      • Pavels
        Member
        • Oct 2011
        • 83

        #4
        Passing "filter": "lastvalue" to item.get doesn't do anything. The filter parameter is an object with property-value pairs.

        Comment

        Working...