Perl / 运行 SNMP 查询时作为哈希引用的未定义值

问题描述 投票:0回答:1

我对 Perl 还很陌生,并且编写了一个脚本来轮询网络设备以获取 sysUptime 数据。它首先在数据库中查询可能的主机,以数组形式返回存储在数据库中的信息,然后根据每个数组元素的 IP 地址,继续轮询主机的正常运行时间。该脚本如下所示(包含相关部分):

Net::SNMP

该脚本每次都适用于可访问的主机(并返回正确的 sysUptime 响应)。典型的有效 
use Net::SNMP; # Loop through the DB array while( my @row = $sth->fetchrow_array() ) { # Dereference into columns my ( $hostname, $ip, $vendor, $model, $status, $queue ) = @row; # Pad and print printf( "%-24s%-18s%-16s%-20s%-16s%-14s", $hostname, $ip, $vendor, $model, $status, $queue ); # Open the SNMP session my ($session, $error) = Net::SNMP->session( -hostname => $ip, -community => 'communityname', -version => 'v2c', -timeout => 5, -retries => 0 ); # Report error and close it the session doesn't open if( !defined $session ) { printf "[SESSION ERROR] %s\n", $error; $session->close(); } # Get the host uptime. # *** This is the line where Perl fails with the error message. *** my $snmp_response = $session->get_request( -varbindlist => [ ".1.3.6.1.2.1.1.3.0" ] )->{".1.3.6.1.2.1.1.3.0"}; # If we don't get a response as the var isn't getting defined, report and close if( !defined $snmp_response ) { printf "[RESPONSE ERROR]: %s\n", $error; $session->close(); # Otherwise print the query result and then close } else { print $snmp_response; $session->close(); } }

看起来像这样:

@row

脚本在第一个无法访问的实例处因
router10.10.10.1CiscoISR4221ProdQ1

而终止,我不明白为什么会发生这种情况。我在会话中使用了

"Can't use an undefined value as a HASH reference at script.pl"
,可以看到主机超时了,而不是返回响应超时错误,而是死掉了。
以下输出来自使用 

"-debug => DEBUG_ALL"

标志时的

Net::SNMP->session
输出。
-debug => DEBUG_ALL

无论我增加超时还是重试值,情况都不会改变。我无法理解为什么它适用于工作主机,但在掌握定义错误之前却失败了。

如果我使用

error: [349] Net::SNMP::Dispatcher::_transport_timeout(): No response from remote host "10.10.10.10" error: [2363] Net::SNMP::__ANON__(): No response from remote host "10.10.10.10" debug: [517] Net::SNMP::Dispatcher::_event_delete(): deleted [ARRAY(0x2b8bae8)], list is now empty Can't use an undefined value as a HASH reference at script.pl line 103.

,它仍然不会为失败的主机输出任何内容。对于工作主机,Dumper 输出如下:

Data::Dumper

现在.. 失败主机的罪魁祸首是它的 SNMP 社区与其他主机不同 - 然而,即使如此,脚本不应该已经返回会话错误,因为它无法打开会话有问题的主持人吗?

perl snmp net-snmp perl-hash
1个回答
0
投票

$VAR1 = bless( { '_transport_argv' => [ '-hostname', '10.10.10.1', '-timeout', 5, '-retries', 0 ], '_nonblocking' => 0, '_discovery_queue' => [], '_error' => undef, '_context_name' => undef, '_version' => 1, '_delay' => 0, '_translate' => 255, '_callback' => undef, '_transport' => bless( { '_dest_name' => '��a�(', '_socket' => bless( \*Symbol::GEN16, 'IO::Socket' ), '_sock_name' => '', '_timeout' => 5, '_dest_hostname' => '10.10.10.1', '_max_msg_size' => 1472, '_sock_hostname' => '', '_error' => undef, '_retries' => 0 }, 'Net::SNMP::Transport::IPv4::UDP' ), '_hostname' => '10.10.10.1', '_security' => bless( { '_error' => undef, '_community' => 'communityname', '_version' => 1 }, 'Net::SNMP::Security::Community' ), '_context_engine_id' => undef, '_pdu' => bless( { '_security' => $VAR1->{'_security'}, '_request_id' => 2009673841, '_index' => 48, '_leading_dot' => 1, '_buffer' => '0.communityname�!w�0q0+C�S�f', '_timeout_id' => [], '_callback' => undef, '_transport' => $VAR1->{'_transport'}, '_length' => 48, '_error_index' => 0, '_var_bind_types' => { '.1.3.6.1.2.1.1.3.0' => 67 }, '_version' => 1, '_security_name' => 'community', '_var_bind_list' => { '.1.3.6.1.2.1.1.3.0' => '255 days, 00:18:57.66' }, '_translate' => 255, '_error_status' => 0, '_scoped' => 0, '_var_bind_names' => [ '.1.3.6.1.2.1.1.3.0' ], '_error' => undef, '_pdu_type' => 162 }, 'Net::SNMP::PDU' ) }, 'Net::SNMP' );

这基本上是一样的

my $snmp_response = $session->get_request( -varbindlist => [ ".1.3.6.1.2.1.1.3.0" ] ) ->{".1.3.6.1.2.1.1.3.0"};

问题是当第一行 
my $result = $session->get_request( -varbindlist => [ ".1.3.6.1.2.1.1.3.0" ] ); my $snmp_response = $result->{".1.3.6.1.2.1.1.3.0"};

失败时 - 因为这将返回 undef。然后它会尝试将未定义的值视为哈希引用 - 这正是您得到的错误。

修复方法不是忽略 

get_request

可能会失败。但在将其用作哈希之前请先检查一下。

    

© www.soinside.com 2019 - 2024. All rights reserved.