我想优化我的perl脚本,因为它显示有关网络的信息有点慢
我不知道可以改变或改进什么来促进脚本执行
我操纵了几个哈希,得到:mac add,index等...我认为它有点沉重,但别无选择。
而且,我做了很多SNMP请求,错误的处理可能不是很好
我复制/粘贴我的脚本及其模块
提前感谢您阅读我的代码。
它包含args:
希望这是可以理解的。
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use SnmpUtil;
use AdresseMac;
use Net::SNMP;
use Net::SNMP::Interfaces;
my $ifname;
my $hostname;
my $community;
my $version = 1;
GetOptions( "ifname=s" => \$ifname,
"host=s" => \$hostname,
"community=s" => \$community,
"protocol:s" => \$version);
my $interfaces = Net::SNMP::Interfaces->new(Hostname => $hostname, Community => $community);
my $inter = $interfaces->interface($ifname);
#Get interface $ifname
my $ifindex = $inter->index();
#Vitesse
my $vitesse = $inter->ifHighSpeed();
#Alias
my $ifalias = $inter->ifAlias();
#Seek for VLANs
my $vlan_trouve;
#Listing all VLANS
my $vmVlan = "1.3.6.1.4.1.9.9.68.1.2.2.1.2"; #OID of vlan table
my $vlans = SnmpUtil->new($hostname, $community);
my %vl = $vlans->requeteTable($vmVlan);
$vlans->deconnexion();
#Get the good VLAN corresponding to index interface
$vlan_trouve = $vl{$ifindex};
#Listing : port VLAN <-> @mac
my $dot1dTpFdbAddress = "1.3.6.1.2.1.17.4.3.1.1";
my $dot = SnmpUtil->new($hostname, $community."@".$vlan_trouve);
my %dot1address = $dot->requeteTable($dot1dTpFdbAddress);
#Listing : numPortBridge <-> port VLAN
my $dot1dTpFdbPort = "1.3.6.1.2.1.17.4.3.1.2";
my %portdot = reverse($dot->requeteTable($dot1dTpFdbPort));
#Listing : num Port bridge <-> ID port switch
my $dot1dBasePortIfIndex = "1.3.6.1.2.1.17.1.4.1.2";
my %dotindex = reverse($dot->requeteTable($dot1dBasePortIfIndex));
#Duplex (auto, half or full)
my $oid_cisco_duplex = "1.3.6.1.2.1.10.7.2.1.19.".$ifindex;
my $duplex = $dot->requete($oid_cisco_duplex);
if ($duplex==1) {
$duplex= "Auto";
}
elsif ($duplex==2) {
$duplex = "Half";
}
elsif ($duplex==3) {
$duplex= "Full";
}
#Close connection
$dot->deconnexion();
#Go back up, to find mac add
my $numportbridge = $dotindex{$ifindex};
if (!defined($numportbridge)) {
print "Erreur : $ifindex not found in list : num Port bridge <-> ID port switch\n";
exit 2;
}
my $portVlan = $portdot{$numportbridge};
if (!defined($portVlan)) {
print "Erreur : $numportbridge not found in list : numPortBridge <-> ports du VLAN\n";
exit 3;
}
my $add = uc($dot1address{$portVlan});
if (!defined($add)) {
print "Erreur : $portVlan not found in list : ports du VLAN <-> \@mac\n";
exit 4;
}
$add =~ s/^0X//g;
printf "<b>Port : $ifname</b><br/>Index $ifindex on VLAN : $vlan_trouve<br/>\@mac : $add<br/>Speed=$vitesse Mbps Alias=$ifalias<br/>Duplex: $duplex\n";
这是SnmpUtil.pm:
#!/usr/bin/perl
use strict;
use warnings;
use Net::SNMP;
package SnmpUtil;
our ($session, $error);
sub new {
my ($classe, $hostname, $community) = @_;
my $this = {
"hostname" => $hostname,
"community" => $community
};
bless($this, $classe);
$this->{connexion} = $this->connexion;
return $this;
}
sub connexion {
my ($this) = @_;
($session, $error) = Net::SNMP->session(
-hostname => $this->{hostname},
-community => $this->{community},
-version => "1",
-timeout => 3,
);
request_error_connexion() if (!defined($session));
}
sub request_error_connexion {
my ($this) = @_;
print "Erreur : can't connect to host\n";
print "Erreur : $error\n";
if ($error =~ /The argument "-community" is unknown/)
{
# protocol SNMP version 3 not working
exit 3; # code ret final = 3*256 = 768
}
else
{
exit 1; # code retour final = 1*256 = 256
}
}
sub request_error {
my ($this) = @_;
print "Error : no answer from host\n";
printf "Erreur : %s\n",$session->error;
if ($session->error =~ /No response from remote host/)
{
#host ok, bad community or host refuse connection
$session->close;
exit 2; # code retour final = 2*256 = 512
}
else
{
#can not find table
$session->close;
exit 4; # code retour final = 4*256 = 1024
}
}
sub requeteTable {
my ($this, $oid) = @_;
my $result = $session->get_table( -baseoid => $oid );
request_error() if (!defined($result));
my %tab = ();
foreach my $i (Net::SNMP::oid_lex_sort(keys %{$result})) {
my $index = $i;
$index =~ s/$oid.//;
$tab{ $index } = $result->{$i};
#print $index."--".$result->{$i}."\n";
}
return %tab;
}
sub requete {
my ($this, $oid) = @_;
my $result = $session->get_request($oid);
request_error() if (!defined($result));
return $result->{$oid};
}
sub deconnexion {
my ($this) = @_;
$session->close();
}
1;
AdresseMac.pm模块没用,只是将dec转换为hex&amp; amp;反之亦然。
感谢您的帮助,
找到优化者的巨大回报;)
答案 0 :(得分:6)
您可能不喜欢这个答案,但是Net-SNMP支持使用C-bindings而不是all-in-perl模块实现编写的perl模块(仅称为 SNMP )的原因之一在 Net :: SNMP 中完成的是C绑定明显更快。 Giovanni Marzot编写了Net-SNMP C绑定绑定的初始实现,测得C / perl绑定实现的速度比all-perl版本快10倍。如果您开始进入经过身份验证/加密的SNMPv3,那么它会变得更快。但是,如果这是您问题的根源,我不会知道。只是一个数据点。 perl profiler真的会让你知道。
需要考虑的另一点:如果您要查询大量主机,请考虑构建代码,以便您可以使用异步请求一次发送多个查询,并使用SNMPv2c同时使用GetBulk请求。这两个优化也将大大提高速度。
已更新,每个请求都包含链接:
Net-SNMP:http://www.net-snmp.org/并下载:http://www.net-snmp.org/download.html。
Net-SNMP的perl常见问题解答:http://www.net-snmp.org/wiki/index.php/FAQ:Perl
一个温和的过时手册页:http://metacpan.org/pod/SNMP
请注意,Net-SNMP有一个你可能感兴趣的gettable()函数,可以进行大量的优化。