这需要对 RANCID 代码进行一些黑客攻击来处理 - 没有什么特别复杂的,我基本上是预先运行一个遥控器show context
并使用它的输出来构建脚本其余部分的命令列表。
这里有一些代码片段来展示我所做的事情(抱歉,格式很奇怪,我是这个网站的新手,还不知道所有的技巧):
\##### Main
\# Get the list of contexts from the FW. fwsmlogin handles multi-context ASAs.
open(INPUT,"fwsmlogin -t $timeo -c \"changeto system;show context\" $host </dev/null |") || die "fwsmlogin failed for $host: $!\n";
$ContextFlag = 0;
$ModeFlag = 0;
while (<INPUT>) {
tr/\015//d;
print STDERR ("Processing line: $_") if ($DEBUG);
if ( /^Context Name/ ) {
$ContextFlag = 1;
if ( / Mode / ) {$ModeFlag = 1}
}
if ( /Connection.*closed/ ) {
print STDERR ("\nDEBUG: Connection closed\n\n") if ($DEBUG);
$clean_run=1;
last;
}
if ( /^Error:/ ) {
print STDOUT ("$host fwsmlogin error: $_");
print STDERR ("$host fwsmlogin error: $_") if ($DEBUG);
$clean_run=0;
last;
}
if ( /^Total active Security Contexts: (\d+)/ ) {
$ContextCount = $1;
last;
}
if ( $ContextFlag ) {
if ( $ModeFlag && /^.(\S+)\s+\S+\s+\S+\s+\S+\s+\S+$/ ||
!$ModeFlag && /^.(\S+)\s+\S+\s+\S+\s+\S+$/ ) {
print STDERR ("$host matched context $1\n") if ($DEBUG);
push @ContextList, $1;
next;
}
}
}
close INPUT;
print STDERR ("\nDEBUG: Preprocessing found $ContextCount contexts: @ContextList\n\n") if ($DEBUG);
if (scalar @ContextList ne $ContextCount) {
print STDERR ("\nERROR: Context count mismatch, count = $ContextCount, List = @ContextList\n\n");
exit 1;
}
%commands=(
'changeto context' => "ChangeContext",
'changeto system' => "IgnoreOutput",
'dir all-filesystems' => "DirAll",
'show context' => "ShowFWContext",
'show failover' => "ShowFailover",
'show mode' => "ShowMode",
'show resource acl-partition' => "ShowResourceACL",
'show resource allocation' => "ShowResourceAlloc",
'show resource partition' => "ShowResourcePart",
'show resource rule' => "ShowResourceRule",
'show resource usage' => "ShowResourceUsage",
'show run' => "ShowRun",
'show version' => "ShowVersion"
);
.
.
.
\## Add the commands to pull the config for each context
foreach my $context (@ContextList) {
$commands{"changeto context $context"} = "ChangeContext";
push @commands, "changeto context $context", "show failover", "show run";
}
$cisco_cmds=join(";",@commands);
$cmds_regexp=join("|",@commands);
我认为这就是您处理多个上下文真正需要的全部内容——如果您相当熟悉 Perl,那么了解它是如何工作的应该不会太难。
顺便说一句,我还将大部分子例程移到了单独的库中,因此在处理自定义版本时,我可以使用适当的“use lib”和“use”语句包含所需的子例程 - 例如 CatOS 设备的自定义脚本将具有这:
use lib '/home/rancid/lib';
use RANCIDsubs;
use CatOSsubs;
而对于 IOS 设备,我们将“使用 CatOSsubs”替换为“使用 IOSsubs”;对于我们“使用 ACEsubs”的 ACE30 和 ACE4710 设备;对于带有“使用 F10subs”等的 Force10 开关,这使得为您需要的任何目的编写自定义 RANCID 脚本变得更加容易。
至于 fwsmlogin,多年来我为各种其他设备类型创建了许多定制版本的 clogin;fwsmlogin 就是其中之一。它与 clogin 没有太大区别——我主要添加了注释并删除了不需要的代码(例如“proc 标签”,这是不必要的,因为我们不使用 Xterm)。唯一重要的更改就在此脚本的末尾,因为防火墙上禁用分页所需的命令与 IOS/CatOS 中所需的命令不同。
要创建您自己的 fwsmlogin,请编辑 clogin 的副本,找到文件末尾附近的“elseif { $do_script }”行,并将后面的部分更改为如下所示:
:
:
} elseif { $do_script } {
send "term pager 0\r"
sleep 0.2
expect -re $prompt {}
source $sfile
close
} else {
:
:
您的格式可能看起来不同,但弄清楚这一点应该不难。