0

I am working on monitoring a Cisco device where I would need to parse the snmp output and print it in separate more verbose lines.

Through the command line I can do this:

snmpwalk -m /usr/share/snmp/mibs/CISCO-UNIFIED-COMPUTING-STORAGE-MIB.my -v2c -c opennms-Priv X.X.X.X .1.3.6.1.4.1.9.9.719.1.45.4.1.18 2>/dev/null | awk '{print $4}' | while read -r line ; do echo "Drive $line" ;  done

Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)
Drive online(1)

However when I use the same in a script:

#!/bin/bash
Output=`snmpwalk -m /usr/share/snmp/mibs/CISCO-UNIFIED-COMPUTING-STORAGE-MIB.my -v2c -c opennms-Priv 10.201.1.131 .1.3.6.1.4.1.9.9.719.1.45.4.1.18 2>/dev/null | awk '{print $4}'`

while read -r line ; do
        echo "Drive $line";

done << $Output

I get this,

bash -x CIMC-Monitong.sh
++ snmpwalk -m /usr/share/snmp/mibs/CISCO-UNIFIED-COMPUTING-STORAGE-MIB.my -v2c -c opennms-Priv X.X.X.X .1.3.6.1.4.1.9.9.719.1.45.4.1.18
++ awk '{print $4}'
+ Output='online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)
online(1)'
CIMC-Monitong.sh: line 9: warning: here-document at line 7 delimited by end-of-file (wanted `$Output')
+ read -r line
+ echo 'Drive '
Drive
+ read -r line
+ echo 'Drive '
Drive
+ read -r line

What am I missing?


Edit: The reason I didn't pipe it is, right now I am getting output similar to this:

Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1) Drive online(1)

But I expect something like this:

Drive1 online(1) Drive2 online(1) Drive3 online(1) Drive4 online(1) Drive5 online(1) Drive6 online(1) Drive7 online(1) Drive8 online(1) Drive9 online(1) Drive10 online(1) Drive11 online(1) Drive12 online(1) Drive13 online(1) Drive14 online(1) Drive15 online(1) Drive16 online(1)

Michael Mrozek
  • 93,103
  • 40
  • 240
  • 233
pradeep s
  • 1
  • 1
  • 1

1 Answers1

1

The <<$Output in the script is interpreted as the start of a here-document.

Usually a here-document is written as, for example,

cat <<END_OF_INPUT
.
.
.
.
END_OF_INPUT

... but it's totally fine to use $Output or any other string as a here-document delimiter.

You probably meant to use <$Output, but that would have been wrong too, as that would have been taken as trying to read from the file $Output, which is not a filename but the output from your pipeline.

Try piping the output to the while-loop instead, just like you did on the command line:

#!/bin/bash

snmpwalk -m /usr/share/snmp/mibs/CISCO-UNIFIED-COMPUTING-STORAGE-MIB.my \
  -v2c -c opennms-Priv X.X.X.X .1.3.6.1.4.1.9.9.719.1.45.4.1.18 2>/dev/null |
awk '{print $4}' |
while read -r line; do 
  echo "Drive $line"
done

I tend to use printf rather than echo when the output needs to contain user-supplied data (any data coming from outside the script, really):

printf 'Drive %s\n' "$line"

See "Why is printf better than echo?"

Updated:

If your output needs to look like

Drive1 online(1)
Drive2 online(1)
... etc.

with the number after Drive being strictly incrementing by one for each line, then you need a counter in the loop:

while read -r line; do 
  printf 'Drive%d %s\n' "$(( ++count ))" "$line"
done
Kusalananda
  • 333,661