大家好,感谢您的阅读,
我正在尝试编写一个脚本,该脚本将通过Cisco Configs进行解析,并确定特定VLAN中的接口与否,以及它们是否已关闭。我认为解析数组并搜索我正在寻找的项目并为它们设置变量很容易我遇到了一些问题。下面是脚本的基本部分,它将文件读入数组,而echo只是转储数组。我正在寻找的是一种读取数组的方法:
基本流程是脚本(interfaces.sh)读入任何* .cfg文件并以数组形式读取接口。此时,它会解析搜索这些字段的数组。如果找到,请设置稍后要使用的值。最后,它获取VLAN和isShut的值,并根据它们的值,报告接口是否在vlan 2中而不是关闭或在另一个vlan中关闭。
## BEGIN interfaces.sh ##
#!/bin/bash
clear
ls *.cfg | while read config; do
IFS=$'\r\n' interfaces=(`sed -n '/^interface/,/!/p' $config `)
tLen=${#interfaces[@]}
printf "\b Starting $config... \n"
for (( i=0; i<${tLen}; i++ ))
do
echo "${interfaces[$i]}"
done
printf "\n\n"
done
#!/bin/bash
clear
ls *.cfg | while read config; do
IFS=$'\r\n' interfaces=(`sed -n '/^interface/,/!/p' $config `)
tLen=${#interfaces[@]}
printf "\b Starting $config... \n"
isInt=0
isShut=0
VLAN=0
for (( i=0; i<${tLen}; i++ ))
do
if [[ $(echo "${interfaces[$i]}" | grep interface | grep net) ]]; then
int_name=${interfaces[$i]}
isInt=1
fi
if [[ $(echo "${interfaces[$i]}" | grep "access vlan" | grep -v "access vlan 2$") ]]; then
VLAN="vlan1"
fi
if [[ $(echo "${interfaces[$i]}" | grep "access vlan 2$") ]]; then
VLAN="vlan2"
fi
if [[ $(echo "${interfaces[$i]}" | grep -v " shutdown$") ]]; then
isShut="notShutdown"
fi
if [[ $(echo "${interfaces[$i]}" | grep " shutdown$") ]]; then
isShut="shut"
fi
# This put here to test if the variables vlan and isShut is being set.
# IF you uncomment this line you can see that the values are set then
# on the next pass it is changed of some of the values. I dont know
# how to fix this.
#echo " $int_name vlan=$VLAN isShut=$isShut"
# Below is the results of the value changing
# interface Ethernet2/3 vlan=vlan1 isShut=notShutdown
# interface Ethernet2/3 vlan=vlan2 isShut=notShutdown
# interface Ethernet2/3 vlan=vlan2 isShut=notShutdown
# interface Ethernet2/3 vlan=vlan2 isShut=shut
# interface Ethernet2/3 vlan=vlan2 isShut=notShutdown
# interface Ethernet2/3 vlan=vlan2 isShut=notShutdown
# interface Ethernet2/3 is in vlan 2 and is not shutdown
# End of interface section so reset counters
if [[ "${interfaces[$i]}" == '!' ]]
then
if [[ "$VLAN" == "vlan1" && "$isShut" == "notShutdown" ]]; then
echo "$int_name is NOT in vlan 2 and is not shutdown"
fi
if [[ "$VLAN" == "vlan1" && "$isShut" == "shut" ]]; then
echo "$int_name is NOT in vlan 2 and is shutdown"
fi
if [[ "$VLAN" == "vlan2" && "$isShut" == "notShutdown" ]]; then
echo "$int_name is in vlan 2 and is not shutdown"
fi
if [[ "$VLAN" == "vlan2" && "$isShut" == "shut" ]]; then
echo "$int_name is in vlan 2 and is shutdown"
fi
isInt=0
isShut=0
vlan=0
fi
done
printf "\n\n"
done
# Save this section as config.txt
Current configuration : 2271 bytes
!
! Last configuration change at 18:30:45 CET Fri Jul 25 2014
!
version 15.0
no service pad
service timestamps debug datetime msec
service timestamps log datetime msec
no service password-encryption
!
hostname SW1
!
boot-start-marker
boot-end-marker
!
!
enable password cisco
!
no aaa new-model
clock timezone CET 1
!
ip cef
no ip domain-lookup
!
ipv6 unicast-routing
ipv6 cef
vtp domain CCIE
vtp mode transparent
!
!
!
spanning-tree mode pvst
spanning-tree extend system-id
!
vlan internal allocation policy ascending
!
vlan 11
!
!
!
!
!
!
!
interface Loopback0
ip address 6.6.7.7 255.255.255.255
!
interface Ethernet0/0
duplex auto
shutdown
!
interface Ethernet0/1
no switchport
ip address 6.6.17.7 255.255.255.0
duplex auto
!
interface Ethernet0/2
duplex auto
!
interface Ethernet0/3
duplex auto
!
interface Ethernet1/0
switchport access vlan 20
switchport mode access
duplex auto
!
interface Ethernet1/1
switchport access vlan 5
switchport mode access
duplex auto
!
interface Ethernet1/2
switchport access vlan 2
switchport mode access
shutdown
duplex auto
!
interface Ethernet1/3
switchport access vlan 2
switchport mode access
duplex auto
!
interface Ethernet2/0
switchport access vlan 2
switchport mode access
duplex auto
!
interface Ethernet2/1
switchport access vlan 2
switchport mode access
duplex auto
!
interface Ethernet2/2
switchport access vlan 40
switchport mode access
duplex auto
!
interface Ethernet2/3
switchport access vlan 2
switchport mode access
shutdown
duplex auto
!
interface Ethernet3/0
switchport access vlan 10
switchport mode access
shutdown
duplex auto
!
interface Ethernet3/1
switchport access vlan 10
switchport mode access
shutdown
duplex auto
!
interface Ethernet3/2
switchport access vlan 10
switchport mode access
shutdown
duplex auto
!
interface Ethernet3/3
switchport access vlan 2
switchport mode access
shutdown
duplex auto
!
interface Vlan1
no ip address
shutdown
!
interface Vlan123
ip address 6.6.123.7 255.255.255.0
shutdown
!
!
ip forward-protocol nd
no ip http server
!
!
!
!
!
control-plane
!
!
line con 0
exec-timeout 0 0
privilege level 15
password cisco
logging synchronous
line aux 0
line vty 0 4
privilege level 15
password cisco
login
transport input all
!
end
我希望我已经解释得这么好了。对于那些聪明的家伙来说,这可能很简单,但我正在努力解决这个问题。
答案 0 :(得分:1)
我已经编写了一个Python 2.7脚本,并且我试图让它变得健壮。我使用IOS配置文件解析器(ciscoconfparse)库来避免我自己的解析尝试中的错误。我已经给它一个命令行界面,以便查看vlan 2上的接口状态:
$ python interfaces.py --vlan 2 /path/to/ios.cfg
<强>安装强>
.py
(例如interfaces.py
)<强> interfaces.py 强>
#!/usr/bin/env python
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from argparse import ArgumentParser
from itertools import ifilter
import sys
from ciscoconfparse import CiscoConfParse
INTERFACE_REGEX = 'interface'
SWITCHPORT_REGEX = 'switchport access vlan'
def main(argv=None):
args = parse_argv(argv=argv)
parse = CiscoConfParse(args.conf_path)
objs = parse.find_objects_w_child(INTERFACE_REGEX, SWITCHPORT_REGEX)
records = (Record.from_ios_object(obj) for obj in objs)
if args.vlan:
records = ifilter(lambda r: r.vlan == args.vlan, records)
for record in sorted(records, key=lambda r: r.name):
print(record)
def parse_argv(argv=None):
if argv is None:
argv = sys.argv
parser = ArgumentParser()
parser.add_argument('--vlan', type=int)
parser.add_argument('conf_path')
return parser.parse_args(args=argv[1:])
class Record:
def __init__(self, name, vlan, is_shutdown):
self.name = name
self.vlan = vlan
self.is_shutdown = is_shutdown
def __str__(self):
if self.is_shutdown:
state = 'shutdown'
else:
state = 'running'
return '{name} {vlan} {state}'.format(
name=self.name,
vlan=self.vlan,
state=state
)
@classmethod
def from_ios_object(cls, obj):
tokens = obj.text.split()
if len(tokens) != 2:
raise ValueError('Expected 2 tokens, found ' + len(tokens))
name = tokens[1]
children = obj.re_search_children(SWITCHPORT_REGEX)
if len(children) != 1:
raise ValueError('Expected 1 matching child, found ' +
len(children))
vlan = int(children[0].re_match('(\d+)$'))
is_shutdown = bool(obj.re_search_children('shutdown'))
return cls(name, vlan, is_shutdown)
if __name__ == '__main__':
sys.exit(main())
答案 1 :(得分:0)
将输入的每一行存储为数组中的单独元素会使处理变得复杂。如果将所有接口定义合并到一个数组元素中,它将简化您对简单字符串搜索的查找。 AWK迷你状态机就是这样做的一种方式。
#!/bin/bash
ls *.cfg | while read config; do
interfaces=()
IFS=$'\n' # We'll delimit the records with this
count=0
printf "\b Starting $config... \n"
for i in $(awk '# ^interface = start of interface def; insert delimiter, set flag.
/^interface Ethernet/{inside_int=1}
# ! = end of interface def; unset flag.
(/!/ && inside_int){inside_int=0; print}
# if flag is set, print line
inside_int{printf "%s ", $0}
' config.cfg ); do
# append to interfaces array
interfaces=(${interfaces[@]} $i)
# Create three arrays with interface data
# Interface name
intname[$count]=$( echo "$i}" | sed -n "s/interface \([^ ]*\).*/\1/p" )
# Interface VLAN
vlan[$count]=$( echo "$i}" | sed -n 's/interface.*switchport access vlan \([^ ]*\).*/\1/p' )
# Interface up/down (0/1) status
isdown[$count]=$( echo "$i}" | grep -c shutdown )
((count++))
done
# Loop and display values.
for (( i=0; i<${#interfaces[@]}; i++ )); do
echo -e "Int:${intname[$i]}\tvlan:${vlan[$i]}\tisdown:${isdown[$i]}"
done
done
${intname[@]}
,${vlan[@]}
和${isdown[@]}
数组包含您要查找的各个值。 ${interfaces[@]}
数组包含每个接口定义作为单独的元素,可以对其他数据进行字符串搜索。
答案 2 :(得分:0)
您不应尝试使用bash
脚本解析分层文本文件(如Cisco IOS配置)...使用预制配置解析库...
改进@ PeterSutton的答案...... CiscoConfParse支持自动vlan解析,如果你用factory=True
进行解析(是的,我知道这仍然没有记录,但你可以找到所有可能的解析ciscoconfparse/models_cisco.py
来源中的值...)
解析接口名称,switchport状态和访问vlan编号的代码就这么简单......
from ciscoconfparse import CiscoConfParse
from prettytable import PrettyTable
parse = CiscoConfParse('config.text', factory=True)
table = PrettyTable(['Intf Name', 'Switchport?', 'Access Vlan (0 is no vlan)'])
for intf_obj in parse.find_objects('^interface'):
table.add_row([intf_obj.name, intf_obj.is_switchport, intf_obj.access_vlan])
print table
当你运行它时,你得到一个文本表......
(py27_test)[mpenning@tsunami ~]$ python example.py
+-------------+-------------+----------------------------+
| Intf Name | Switchport? | Access Vlan (0 is no vlan) |
+-------------+-------------+----------------------------+
| Loopback0 | False | 0 |
| Ethernet0/0 | False | 0 |
| Ethernet0/1 | False | 0 |
| Ethernet0/2 | False | 0 |
| Ethernet0/3 | False | 0 |
| Ethernet1/0 | True | 20 |
| Ethernet1/1 | True | 5 |
| Ethernet1/2 | True | 2 |
| Ethernet1/3 | True | 2 |
| Ethernet2/0 | True | 2 |
| Ethernet2/1 | True | 2 |
| Ethernet2/2 | True | 40 |
| Ethernet2/3 | True | 2 |
| Ethernet3/0 | True | 10 |
| Ethernet3/1 | True | 10 |
| Ethernet3/2 | True | 10 |
| Ethernet3/3 | True | 2 |
| Vlan1 | False | 0 |
| Vlan123 | False | 0 |
+-------------+-------------+----------------------------+
(py27_test)[mpenning@tsunami ~]$
您可以使用Inline::Python
将ciscoconfparse
嵌入到perl脚本中......但是您仍然需要在python中编写,因此我不确定任务的重点是什么这很简单。
免责声明:我是CiscoConfParse的作者