Perl/Net::SNMP:脚本太慢,需要优化

Perl/Net::SNMP:脚本太慢,需要优化,perl,optimization,snmp,Perl,Optimization,Snmp,我想优化我的perl脚本,因为它显示有关网络的信息有点慢。 我不知道有什么可以改变或改进以提高脚本执行。 我操纵了几个散列,以得到:macadd,index,等等。。。我觉得有点重,但别无选择。 此外,我做了很多SNMP请求,错误处理可能不是很好。 我复制/粘贴脚本及其模块。 提前感谢您阅读我的代码 它接受args: 接口名称(例如FastEthernet0/9或FastEthernet0/1…) 主机名:交换机的ip地址 社区(通常=公共) 希望这是可以理解的 #!/usr/bin/perl


我想优化我的perl脚本,因为它显示有关网络的信息有点慢。
我不知道有什么可以改变或改进以提高脚本执行。
我操纵了几个散列,以得到:macadd,index,等等。。。我觉得有点重,但别无选择。
此外,我做了很多SNMP请求,错误处理可能不是很好。
我复制/粘贴脚本及其模块。
提前感谢您阅读我的代码

它接受args:

  • 接口名称(例如FastEthernet0/9或FastEthernet0/1…)
  • 主机名:交换机的ip地址
  • 社区(通常=公共)
  • 希望这是可以理解的

     #!/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";
    
    AdresseMac.pm模块是无用的,它只是将dec转换为十六进制,反之亦然

    谢谢你的帮助,
    对发现优化的人的巨大奖励;)


    PS:忘了说,我在cisco switch 2960上工作。

    您可能不喜欢这个答案,但NetSNMP支持使用C绑定编写的perl模块(称为SNMP)而不是在Net::SNMP中完成的全套perl模块实现的原因之一是C绑定速度明显更快。Giovanni Marzot编写了NetSNMP C-binding绑定的初始实现,他测量C/perl绑定实现的速度比全perl版本快10倍。如果您开始进入经过身份验证/加密的SNMPv3,那么它会变得更快。然而,我不知道这是否是你问题的根源。只是一个数据点。perl分析器会真正让您知道

    需要考虑的另一点是:如果要查询大量主机,请考虑构建代码,以便可以使用异步请求和使用SNMPv2c的GetBulk请求一次发送多个查询。这两种优化也将大大提高速度

    更新了每个请求的链接:

    • Net SNMP:和下载:

      • NetSNMP工具包附带了它的perl模块。使用--with perl模块配置网络SNMP
    • Net SNMP的perl常见问题解答:

    • 稍微过时的手册页:


    请注意,Net SNMP有一个您可能感兴趣的gettable()函数,它可以进行大量优化。

    您可能不喜欢这个答案,但这是Net SNMP支持perl模块(称为SNMP)的原因之一使用C绑定而不是在Net::SNMP中完成的all-in-perl模块实现编写的C绑定速度要快得多。Giovanni Marzot编写了NetSNMP C-binding绑定的初始实现,他测量C/perl绑定实现的速度比全perl版本快10倍。如果您开始进入经过身份验证/加密的SNMPv3,那么它会变得更快。然而,我不知道这是否是你问题的根源。只是一个数据点。perl分析器会真正让您知道

    需要考虑的另一点是:如果要查询大量主机,请考虑构建代码,以便可以使用异步请求和使用SNMPv2c的GetBulk请求一次发送多个查询。这两种优化也将大大提高速度

    更新了每个请求的链接:

    • Net SNMP:和下载:

      • NetSNMP工具包附带了它的perl模块。使用--with perl模块配置网络SNMP
    • Net SNMP的perl常见问题解答:

    • 稍微过时的手册页:


    请注意,Net SNMP有一个您可能感兴趣的gettable()函数,它可以进行大量优化。

    好的,谢谢您的帖子,我只使用SNMP v1,他们不想使用较新版本的SNMP。您是否有一些链接可用于在Perl中使用更快的SNMP库?好的,谢谢您的帖子,我只使用SNMP v1,他们不想使用更新版本的SNMP。您是否有一些链接可以与Perl一起使用更快的SNMP库?
    #!/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;