bashawksnmpcacti

Simple script to put snmpbulkwalk results into variables, how can I put all data in 2 arrays?


I made a simple script for representing a Cacti Graph, and it works, but obviously it's not really optimized, because I'm doing 8 queries with snmpbulkwalk and splitting by line number (FNR==x), while I could have done just 2 queries, using 2 arrays, one for the first OID and the other for the second OID. I'm doing myself this question because obviously for Cacti the faster it's the script, the better can the Poller handle the data input.

#!/bin/bash
#hwCBQoSIfQueueMatchedBytes
qos_match_2=$(snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.2 | awk 'FNR==2 {print $4}')
qos_match_3=$(snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.2 | awk 'FNR==3 {print $4}')
qos_match_4=$(snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.2 | awk 'FNR==4 {print $4}')
#hwCBQoSIfQueueDiscardedBytes
dis_match_2=$(snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.6 | awk 'FNR==2 {print $4}')
dis_match_3=$(snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.6 | awk 'FNR==3 {print $4}')
dis_match_4=$(snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.6 | awk 'FNR==4 {print $4}')

printf "qos_match_2:$qos_match_2 "
printf "qos_match_3:$qos_match_3 "
printf "qos_match_4:$qos_match_4 "
printf "dis_match_2:$dis_match_2 "
printf "dis_match_3:$dis_match_3 "
printf "dis_match_4:$dis_match_4 "
printf "\n"

A sample output of the 'snmpbulkwalk' command on a host would be:

SNMPv2-SMI::enterprises.2011.5.25.32.1.1.5.1.6.1.2.3.2.1 = Counter64: 0
SNMPv2-SMI::enterprises.2011.5.25.32.1.1.5.1.6.1.2.3.2.2 = Counter64: 431032480
SNMPv2-SMI::enterprises.2011.5.25.32.1.1.5.1.6.1.2.3.2.3 = Counter64: 12456864036
SNMPv2-SMI::enterprises.2011.5.25.32.1.1.5.1.6.1.2.3.2.4 = Counter64: 69821418510
SNMPv2-SMI::enterprises.2011.5.25.32.1.1.5.1.6.1.2.3.2.5 = Counter64: 0

and a sample output of the script would be

qos_match_2:431741706 qos_match_3:12464887554 qos_match_4:69827660661 dis_match_2:0 dis_match_3:345524650 dis_match_4:0 

Where each line corresponds to a Qos class, and we're using only Class 2, 3 and 4

The OID .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.2 matches QoS matched bytes and the OID .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.6 matches instead QoS discarded bytes.

How can I solve this?

In pseudo-code I would like to to:

#hwCBQoSIfQueueMatchedBytes
qos_match=$(snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.2)

printf "qos_match2:" $qos_match[0]
printf "qos_match3:" $qos_match[1]
printf "qos_match4:" $qos_match[2]

and so on


UPDATE 07.05.2020 after luciole75w suggestion:

#!/bin/bash

#set -x

MYCOMMUNITY="mycommunity"

mapfile -t qos_match < <(
    snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.2 |
    awk '2 <= NR && NR <= 4 { print $4 }'
)

mapfile -t dis_match < <(
    snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.6 |
    awk '2 <= NR && NR <= 4 { print $4 }'
)

for n in {2..4}; do
    printf "qos_match_$n:${qos_match[n-2]} "
done
for n in {2..4}; do
    printf "dis_match_$n:${dis_match[n-2]} "
done

printf "\n"

#set +x

Solution

  • To save output lines in a bash array variable you can use mapfile with a process substitution as input. The following command should work for you, noting that I don't know snmpbulkwalk so I just copy your command as is.

    mapfile -t qos_match < <(
        snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.2 |
        awk '2 <= NR && NR <= 4 { print $4 }'
    )
    
    for n in {2..4}; do
        echo qos_match$n: "${qos_match[n-2]}"
    done
    

    If your goal is actually the output string (only) and not the arrays, here is an alternative command to get your expected output more efficiently without using shell variables.

    awk '
        2 <= FNR && FNR <= 4 {
            printf "%s_match_%d:%s%s", name, FNR, $4, (++n < 6 ? OFS : ORS)
        }
    ' name=qos <(
        snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.2
    ) name=dis <(
        snmpbulkwalk -v 2c -c $MYCOMMUNITY $1 .1.3.6.1.4.1.2011.5.25.32.1.1.5.1.6.1.6
    )