我对 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 社区与其他主机不同 - 然而,即使如此,脚本不应该已经返回会话错误,因为它无法打开会话有问题的主持人吗?
$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
可能会失败。但在将其用作哈希之前请先检查一下。