我正在尝试获取有关VPN连接的状态信息。 它几乎完成了,除了返回实际PH2名称的部分:
#!/bin/bash
OLDIFS=$IFS
export IFS=`/bin/echo -ne " \t\n"`
VPN="VPN-AAA-BBB-1"
ph2table=$(snmpwalk 192.168.1.1 -c public -v2c fgVpnTunEntPhase2Name -m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib | sed "s/FORTINET-FORTIGATE-MIB:://" | sed "s/STRING: //" | grep $VPN)
$ph2table
现在包含:
fgVpnTunEntPhase2Name.71 = VPN-AAA-BBB-1-P2-0.1
fgVpnTunEntPhase2Name.72 = VPN-AAA-BBB-1-P2-0.2
fgVpnTunEntPhase2Name.73 = VPN-AAA-BBB-1-P2-0.3
fgVpnTunEntPhase2Name.74 = VPN-AAA-BBB-1-P2-0.4
fgVpnTunEntPhase2Name.75 = VPN-AAA-BBB-1-P2-1.5
fgVpnTunEntPhase2Name.76 = VPN-AAA-BBB-1-P2-1.6
fgVpnTunEntPhase2Name.77 = VPN-AAA-BBB-1-P2-1.7
fgVpnTunEntPhase2Name.78 = VPN-AAA-BBB-1-P2-1.8
fgVpnTunEntPhase2Name.79 = VPN-AAA-BBB-1-P2-2.9
fgVpnTunEntPhase2Name.80 = VPN-AAA-BBB-1-P2-3.10
clean=$(echo $ph2table | sed 's/fgVpnTunEntPhase2Name/fgVpnTunEntStatus/' | sed 's/=.*//')
$clean
现在包含:
fgVpnTunEntStatus.71
fgVpnTunEntStatus.72
fgVpnTunEntStatus.73
fgVpnTunEntStatus.74
fgVpnTunEntStatus.75
fgVpnTunEntStatus.76
fgVpnTunEntStatus.77
fgVpnTunEntStatus.78
fgVpnTunEntStatus.79
fgVpnTunEntStatus.80
export IFS=$OLDIFS
for i in "$clean" ; do snmpget 192.168.1.1 -c public -v2c $i -m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib ; done | sed "s/FORTINET-FORTIGATE-MIB::fgVpnTunEntStatus.//" | sed 's/= INTEGER: //'
这将返回:
71 up(2)
72 down(1)
73 up(2)
74 up(2)
75 up(2)
76 up(2)
77 up(2)
78 up(2)
79 up(2)
80 up(2)
我想要得到的最终结果是:
VPN-AAA-BBB-1-P2-0.1 71 up(2)
VPN-AAA-BBB-1-P2-0.2 72 down(1)
VPN-AAA-BBB-1-P2-0.3 73 up(2)
VPN-AAA-BBB-1-P2-0.4 74 up(2)
VPN-AAA-BBB-1-P2-1.5 75 up(2)
VPN-AAA-BBB-1-P2-1.6 76 up(2)
VPN-AAA-BBB-1-P2-1.7 77 up(2)
VPN-AAA-BBB-1-P2-1.8 78 up(2)
VPN-AAA-BBB-1-P2-2.9 79 up(2)
VPN-AAA-BBB-1-P2-3.10 80 up(2)
我似乎无法找到将事物合并在一起的方法。有什么想法关于这个?
答案 0 :(得分:1)
我认为最简单的做法是退后一步:
while read ph; do
# clean is only a single cleaned entry now
clean=$(echo "$ph" | sed 's/fgVpnTunEntPhase2Name/fgVpnTunEntStatus/;s/ =.*//')
# status for that one entry
status=$(snmpget 192.168.1.1 -c public -v2c "$clean" -m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib | sed 's/FORTINET-FORTIGATE-MIB::fgVpnTunEntStatus.//; s/= INTEGER: //')
# isolate VPN-AAA-BBB-1-P2-x.y part
cur=$(echo "$ph" | sed 's/.* = //')
# print the stuff we want.
echo "$cur $status"
# instead of feeding "$phtable2" to the loop, it would also be possible to
# pipe the output of the command that was put there directly through the loop,
# as in command | while read ph; do ... done
done <<< "$phtable2"
代码必须未经测试,因为我没有您的SNMP设置,但我希望从中获得一般的想法。
我还要看一下snmp工具的文档,看看是否有更直接的方法来隔离变量的值,而不是通过sed将它全部管道化。如果更新工具并且其输出格式稍有变化,那么这可能会成为一个问题。
答案 1 :(得分:1)
在变量中捕获内容并不是通常由资深shell脚本程序员完成的。只需将所有内容保存在管道中。
这很简单,但我想解释为什么我改变了一些东西,所以下面包含一个带注释的版本。
#!/bin/bash
VPN="VPN-AAA-BBB-1"
snmpwalk 192.168.1.1 -c public -v2c fgVpnTunEntPhase2Name \
-m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib |
sed -e 's/FORTINET-FORTIGATE-MIB:://' -e 's/STRING: //' -e "/$VPN/!d" |
while read i _ id; do
snmpget 192.168.1.1 -c public -v2c "$i" \
-m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib |
sed -e 's/FORTINET-FORTIGATE-MIB::fgVpnTunEntStatus.//' -e 's/= INTEGER: //' \
-e "s/^/$id /"
done
(这里没有任何特定于Bash的内容,所以你可以将shebang实际更改为#!/bin/sh
。这在这里几乎不重要,但如果你需要在Bash太大或太大的系统上运行它慢或不可用,改为使用Dash的选项可能很有吸引力。)
带注释的版本有点长,并且有一个讨厌的垂直滚动条,但评论解释了我改变了什么以及为什么。
#!/bin/bash
#OLDIFS=$IFS
#export IFS=`/bin/echo -ne " \t\n"`
# No need to export (you don't want or need this in subprocesses)
# No need to echo (bash has adequate internal facilities for representing strings)
# IFS=$' \t\n'
# Commented out because we do the required parsing in sed instead
VPN="VPN-AAA-BBB-1"
#ph2table=$(snmpwalk 192.168.1.1 -c public -v2c fgVpnTunEntPhase2Name \
#-m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib |
#sed "s/FORTINET-FORTIGATE-MIB:://" | sed "s/STRING: //" | grep $VPN)
# No need to use multiple processes; sed can do everything in one go
# No need for a variable -- feed this into a pipeline
snmpwalk 192.168.1.1 -c public -v2c fgVpnTunEntPhase2Name \
-m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib |
sed -e 's/FORTINET-FORTIGATE-MIB:://' -e 's/STRING: //' -e "/$VPN/!d" |
# The following could be added to replace "clean" but we take a different approach
# -e 's/fgVpnTunEntPhase2Name/fgVpnTunEntStatus/' -e 's/=.*//' |
#clean=$(echo $ph2table | sed 's/fgVpnTunEntPhase2Name/fgVpnTunEntStatus/' |
#sed 's/=.*//')|
# No need for a variable
# $ph2table absolutely needs to be quoted here -- "$ph2table"
# but we don't want to do this -- instead, keep this in the output
#export IFS=$OLDIFS
# No longer necessary -- see above
#for i in "$clean" ; do
# Instead of a for loop over a variable, do a while loop over output lines from pipe
# Split into i, equals sign (in $_, which we ignore), and id
while read i _ id; do
#snmpget 192.168.1.1 -c public -v2c $i \
#-m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib ; done |
# Definitely need to quote "$i"
snmpget 192.168.1.1 -c public -v2c "$i" \
-m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib |
#sed "s/FORTINET-FORTIGATE-MIB::fgVpnTunEntStatus.//" |
# sed 's/= INTEGER: //'
# Again, use a single sed invocation
# Factor this inside the while loop, and add the id to the output
sed -e 's/FORTINET-FORTIGATE-MIB::fgVpnTunEntStatus.//' \
-e 's/= INTEGER: //' \
-e "s/^/$id /"
done
答案 2 :(得分:0)
如果这些行肯定会匹配,您可以将它们与paste(1)结合使用。
答案 3 :(得分:0)
我没有测试它,但这样的事情应该有效:
VPN="VPN-AAA-BBB-1" && while read -ra myarr; do
snmp=$(snmpget 192.168.1.1 -c public -v2c "${myarr[0]}" -m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib ; done | sed "s/FORTINET-FORTIGATE-MIB::fgVpnTunEntStatus.//" | sed 's/= INTEGER: //')
echo "${myarr[0]} ${snmp}"
done < <(snmpwalk 192.168.1.1 -c public -v2c fgVpnTunEntPhase2Name -m /usr/share/snmp/mibs/FORTINET-FORTIGATE-MIB.mib | sed "s/FORTINET-FORTIGATE-MIB:://" | sed "s/STRING: //" | grep "${VPN}")
这避免了使用IFS,如果在设置IFS时你的代码退出(没有捕获错误),你可能会有像你说的不可预知的行为。