PerlでCisco操作

スポンサーリンク

実際の構築作業の中で作業前と作業後には全機器のログを取得している方がほとんどだと思います。(取得するログの内容は人や動作要件によってまちまちだと思いますが)数台程度の台数であれば大した手間にもなりませんが100台をこえるぐらいの規模となるとログ取得が結構手間です。

生産性向上というキーワードを良く耳にしますが、こういう機械的な作業こそ自動化すべきという考えからPerlでCisco機器を操作してみました。100台以上ともなればスクリプトの中に書く各機器のIPとかホスト名もそれなりに大変ではありますが、当日の作業時間短縮という意味では大いに効果があるかと。以下の前提条件です。

・Perlを実行するのはLinuxサーバ
・そのLinuxサーバからは全Cisco機器にTelnetでアクセスできる
・そのLinuxサーバにはNet:Telnet:Ciscoモジュールがインストールされている。

まずPerlを実行するLinuxサーバにCiscoモジュールをインストールします。(Perl本体はデフォル トでインストールされています)

# cpan Net::Telnet::Cisco


perlの内容は下記のようになります。

#!/usr/bin/perl
# Ciscoコマンド操作モジュールのロード
use Net::Telnet::Cisco;

# IPアドレス
my %IPAddress = ('hostname1' => 'xx.yy.xx.1',
                 'hostname2' => 'xx.yy.xx.2',
                 'hostname3' => 'xx.yy.xx.3',
                 'hostname4' => 'xx.yy.xx.4',
                 'hostname5' => 'xx.yy.xx.5',
                 'hostname6' => 'xx.yy.xx.6',
                 'hostname7' => 'xx.yy.xx.7',
                 'hostname8' => 'xx.yy.xx.8');

# vtyログインパスワード
my $username  = 'xxx';
my $vtyPasswd = 'yyyyyy';
# ENABLEモード パスワード
my $enPasswd =  'zzzzzz';
# File保存先
my $path='/path/to';

# *--- 設定ここまで ---*
	
# ------------------------------------------------------------------


foreach $key ( keys %IPAddress ){
	# Cisco.pm用オブジェクトの作成 -> ルータに接続
	my $obj_Session= Net::Telnet::Cisco->new( Errmode => "return", \
                                                  Timeout => 30, Host => $IPAddress{$key} );
	$obj_Session->max_buffer_length(50 * 1024 * 1024);
	
	# vtyパスワードを用いてログイン
	$obj_Session->login( Name => $username , Password => $vtyPasswd, );

	# ENABLEモードに昇格
	$obj_Session->enable( $enPasswd );

	# コマンドの実行
	@cmd_output1 = $obj_Session->cmd('show clock');
	@cmd_output2 = $obj_Session->cmd('show runn');
	@cmd_output3 = $obj_Session->cmd('show vlan');
	@cmd_output4 = $obj_Session->cmd('show int');
	@cmd_output5 = $obj_Session->cmd('show int trunk');
	@cmd_output6 = $obj_Session->cmd('show int status');
	@cmd_output7 = $obj_Session->cmd('show int count error');
	@cmd_output8 = $obj_Session->cmd('show spanning-tree');
	@cmd_output9 = $obj_Session->cmd('show spanning-tree blo');
	@cmd_output10 = $obj_Session->cmd('show spanning-tree sum');
	@cmd_output11 = $obj_Session->cmd('show ip int brief');
	@cmd_output12 = $obj_Session->cmd('show ip route');
	@cmd_output13 = $obj_Session->cmd('show ip route ospf');
	@cmd_output14 = $obj_Session->cmd('show ip ospf nei');
	@cmd_output15 = $obj_Session->cmd('show ip ospf dat');
	@cmd_output16 = $obj_Session->cmd('show ntp asso');
	@cmd_output17 = $obj_Session->cmd('show ntp status');
	@cmd_output18 = $obj_Session->cmd('show log');
	@cmd_output19 = $obj_Session->cmd('show tech pass');


	# File名取得
	$name=$path.'/'.$key."_".&YY.&MM.&DD.".txt";

	# コマンド実行結果のアウトプット
	open ( FILE, "> $name" );
	print FILE  '《 show clock 》'."\n";
	print FILE  join('', @cmd_output1)."\n";
	print FILE  '《 show runn 》'."\n";
	print FILE  join('', @cmd_output2)."\n";
	print FILE  '《 show vlan 》'."\n";
	print FILE  join('', @cmd_output3)."\n";
	print FILE  '《 show int 》'."\n";
	print FILE  join('', @cmd_output4)."\n";
	print FILE  '《 show int trunk 》'."\n";
	print FILE  join('', @cmd_output5)."\n";
	print FILE  '《 show int status 》'."\n";
	print FILE  join('', @cmd_output6)."\n";
	print FILE  '《 show int count error 》'."\n";
	print FILE  join('', @cmd_output7)."\n";
	print FILE  '《 show spanning-tree 》'."\n";
	print FILE  join('', @cmd_output8)."\n";
	print FILE  '《 show spanning-tree blo 》'."\n";
	print FILE  join('', @cmd_output9)."\n";
	print FILE  '《 show spanning-tree sum 》'."\n";
	print FILE  join('', @cmd_output10)."\n";
	print FILE  '《 show ip int brief 》'."\n";
	print FILE  join('', @cmd_output11)."\n";
	print FILE  '《 show ip route 》'."\n";
	print FILE  join('', @cmd_output12)."\n";
	print FILE  '《 show ip route ospf 》'."\n";
	print FILE  join('', @cmd_output13)."\n";
	print FILE  '《 show ip ospf nei 》'."\n";
	print FILE  join('', @cmd_output14)."\n";
	print FILE  '《 show ip ospf dat 》'."\n";
	print FILE  join('', @cmd_output15)."\n";
	print FILE  '《 show ntp asso 》'."\n";
	print FILE  join('', @cmd_output16)."\n";
	print FILE  '《 show ntp status 》'."\n";
	print FILE  join('', @cmd_output17)."\n";
	print FILE  '《 show log 》'."\n";
	print FILE  join('', @cmd_output18)."\n";
	print FILE  '《 show tech pass 》'."\n";
	print FILE  join('', @cmd_output19)."\n";
	close ( FILE );
}

# 日付を求める
sub YY{sprintf("%04d",(localtime(shift||time))[5]+1900   )} # 年
sub MM{sprintf("%02d",(localtime(shift||time))[4]+1      )} # 月
sub DD{sprintf("%02d",(localtime(shift||time))[3]        )} # 日


$obj_Session= Net::Telnet::Cisco->newのErrmode => returnを指定しないとサポートされていないコマンドを実行した際にその時点でスクリプトが終了してしまいました。


全て同一のシスコ機種というのはあまりないと思うので入れておいたほうが良いと思います。また、上記はあくまで取得できるログはシスコのみなので他のメーカーのものには非対応です。


単にログ取得だけでは芸がなく、特定のIPアドレスがどの 物理ポート配下にいるのか知りたいといわれたことがあります。IPアドレスを引数に渡すことで即座にどのポート配下なのか出力するスクリプトが以下です。これは各セグメントは/24であり、デフォルトルートが.254であることが前提ですが機種や環境によっては正常に動かない可能性も大いにあるので悪しからず。

#!/usr/bin/perl
# Ciscoコマンド操作モジュールのロード
use Net::Telnet::Cisco;

# vtyログインパスワード
my $username  = 'xxxx';
my $vtyPasswd = 'yyyyyy';
# ENABLEモード パスワード
my $enPasswd =  'zzzzzz';

$IP_address = $ARGV[0];
($ip_1, $ip_2, $ip_3, $ip_4) = split(/\./, $IP_address);

# 接続先IPアドレス
$IPAddress = "$ip_1.$ip_2.$ip_3.254";


# *--- 設定ここまで ---*
	
# ------------------------------------------------------------------

# Cisco.pm用オブジェクトの作成 -> ルータに接続
$obj_Session= Net::Telnet::Cisco->new( Host => $IPAddress );

# vtyパスワードを用いてログイン
$obj_Session->login( Name => $username , Password => $vtyPasswd );

# ENABLEモードに昇格
$obj_Session->enable( $enPasswd );

# HOSTNAME取得 
$hostname = '';
@show_run = $obj_Session->cmd('show runn');
for my $i (@show_run){
	if($i =~ /hostname/) { $hostname = $i; }
}

# MACアドレス取得
@mac_list = $obj_Session->cmd("show ip arp $IP_address");
$str = join('', @mac_list);
if($str =~ /(([a-fA-F\d]{4}\.)([a-fA-F\d]{4}\.)([a-fA-F\d]{4}))/){
   $mac_address = $1;
}else{
   print 'Error!';
   exit;
}

# 物理ポート取得
@port = $obj_Session->cmd("show mac-address-table address $mac_address");
$str  = join('', @port);
if ( $str =~ /(Gi(|gabitEthernet)(\d\/)(\d\/|)(\d\d?))/ ) {
   $mac_port = $1;
}else{
   print 'Error!';
   exit;
}

print "\n";
print "$hostname\n";
print "IPAddress    is    $ip_1.$ip_2.$ip_3.$ip_4\n";
print "MacAddress   is    $mac_address\n";
print "Port         is    $mac_port";
exit 0;


何かの参考になればと思います。

参考URL: http://aerith.mydns.jp/regrets/2006/10/nettelnetcisco.html

スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする