If elsif if snmp issue - perl

I have some devices I want to get the temperature from. Some devices do not give a numeric temperature, just OK or 1. Basically I want to poll on mib then if that is blank poll another, if still blank print problem.
my $walk = `snmpwalk -O n -v 1 -c $community $switchaddr 1.3.6.1.4.1.9.9.13.1.3.1.3`;
$walk = substr("$walk", -3); #remove spacing
#print "\r$switchaddr $walk"
if ($walk =~ /^[0-9]+$/) { #If something is returned
print "$switchaddr $walk";
} elsif ($walk eq "") {
$walk = `snmpwalk -O n -v 1 -c $community $switchaddr 1.3.6.1.4.1.9.5.1.2.17`;
print "$switchaddr $walk\n"; #Should print 1
} else {
print "$switchaddr Problem\n";
}
Thanks for the help.

Use this, a lot better:
#! /usr/local/bin/perl
use strict;
use warnings;
use Net::SNMP;
my $OID = '1.3.6.1.4.1.9.9.13.1.3.1.3';
my ($session, $error) = Net::SNMP->session(
-hostname => shift || 'localhost',
-community => shift || 'public',
);
if (!defined $session) {
printf "ERROR: %s.\n", $error;
exit 1;
}
my $result = $session->get_request(-varbindlist => [ $OID ],);
if (!defined $result) {
printf "ERROR: %s.\n", $session->error();
$session->close();
exit 1;
}
printf "The sysUpTime for host '%s' is %s.\n", $session->hostname(), $result->{$OID};
$session->close();

Related

Use of uninitialized value $login_output in concatenation (.) or string at

in a .pl I have the following error (capture), the script is used through SPECTRUM, a network monitoring tool, and the script is used to capture the running config of a device, what could be the fault ? Thank you.
#!/opt/SPECTRUM/bin/perl -w
# This script will capture the running configuration of a
# Cisco SAN-OS device through an SSH session and print it to STDOUT.
#
# Error Codes:
# 0 = Success
# 255 = Usage error
# 254 = Invalid timeout value
# 252 = Login error
# 249 = Exec prompt not found error
# 244 = Error retrieving configuration
# 245 = Insufficient privileges
# 253 = Unexpected output
#
use strict;
use warnings;
use Net::SSH::Expect;
$ENV{'PATH'} = "/usr/bin:". $ENV{'PATH'};
### Main ###
if( $#ARGV != 4 && $#ARGV != 5 )
{
print "Usage: capture_running.pl <device IP> <user> <pass> <enable_pass>
<login_timeout_in_seconds> <capture_timeout_in_seconds>\n";
print STDERR "Usage: capture_running.pl <deviceIP> <user> <pass>
<enable_pass> <login_timeout_in_seconds> <capture_timeout_in_seconds>\n";
exit 255;
}
elsif( $ARGV[4] < 1 || $ARGV[4] > 600 )
{
print "$ARGV[4] is the login timeout and must be an int between 1 and 600 seconds\n";
print STDERR "$ARGV[4] is the login timeout and must be an int between 1 and 600 seconds\n";
exit 254;
}
elsif( $#ARGV == 5 && ( $ARGV[5] < 1 || $ARGV[5] > 600 ) )
{
print "$ARGV[5] is the capture timeout and must be an int between 1 and 600 seconds\n";
print STDERR "$ARGV[5] is the capture timeout and must be an int between 1 and 600 seconds\n";
exit 254;
}
else
{
my $capture_timeout = $ARGV[4];
if( $ARGV[5] )
{
$capture_timeout = $ARGV[5];
}
my $errorCode = 1;
my #data;
my $errorString = "\nHost $ARGV[0]: \n";
($errorCode, #data) = GetConfig( $ARGV[0], $ARGV[1], $ARGV[2], $ARGV[3],
$ARGV[4], $capture_timeout );
if( $errorCode == 0 )
{
# Success. The running configuration
# content is in the data variable
foreach ( #data ) { print "$_\n" }; # print the configuration to STDOUT
exit 0;
}
else
{
print STDERR $errorString;
if( $errorCode == 245 )
{
print STDERR join " ", #data, "\nEnsure that the device user has
sufficient privileges to disable paging and view the config\n";
}
else
{
print STDERR join " ", #data, "\n";
}
exit $errorCode;
}
}
exit 0;
sub GetConfig
{
my $deviceIP=shift;
my $user=shift;
my $pass=shift;
my $epass=shift;
my $login_timeout=shift;
my $capture_timeout=shift;
my #config;
my $msg;
my $ssh = Net::SSH::Expect->new ( host => $deviceIP,
user => $user,
password=> $pass,
raw_pty => 1,
no_terminal => 0,
timeout => $login_timeout,
ssh_option => '-1 -c DES'
);
my $login_output;
eval { $login_output = $ssh->login(); };
if( $# )
{
$msg = "Login has failed. Output: $login_output";
return( 252, $msg );
}
# login output should contain the right prompt characters
if( $login_output !~ /\>\s*\z/ )
{
$msg = "Login has failed. Didn't see device prompt as expected.";
$ssh->close();
return( 252, $msg );
}
if( $login_output !~ /\>\s*\z/ ) # Replace '#' is the prompt character here
{
# we don't have the '#' prompt, means we still can't exec commands
$msg = "Exec prompt not found.";
$ssh->close();
return( 249, $msg );
}
my $elogin = $ssh->exec("en");
my $elogin2 = $ssh->exec($epass);
if( $elogin2 !~ /\#\s*\z/ ) # Replace '#' is the prompt character here
{
$msg = "Exec prompt not found.";
$ssh->close();
return( 249, $msg );
}
# disable paging
# different commands for different devices, if they don't
# work then we will get messages about problems later
# specifically the "No prompt after 'sh run'" error
# errmsg doesn't get set when these error and if we use print
# and getlines to read for errors it causes problems with print "sh run"
# later.
# $ssh->exec( "term pager 0" );
my $paging = $ssh->exec( "term pager 0" );
if ( $paging =~ /\s?%\s/ )
{
$msg = "Unable to set terminal size to 0 - Insufficient privileges";
$ssh->close();
return( 245, $msg);
}
$ssh->send( "sh run" );
$ssh->timeout( $capture_timeout );
$ssh->peek(0);
while( my $line = $ssh->read_line() )
{
# get configuration content
if( $line !~
/sh run|Building configuration|Current configuration|^\s*$/ )
{
push #config, $line;
}
}
if( #config <= 0 )
{
$msg = "No data retrieved, the capture timeout may be too low.";
$ssh->close();
return( 244, $msg );
}
if( scalar grep { $_ =~ /^%/ } #config )
{
# Ensure show running actually returned the config and not an error
# message containing '%'
return( 245, #config );
}
return( 0, #config ); # everything was okay, return the captured data
}
It would really help us if you took the time to ensure the code you give us is well-formatted and as easy to read as possible.
But the code causing the problem is this:
my $login_output;
eval { $login_output = $ssh->login(); };
if( $# )
{
$msg = "Login has failed. Output: $login_output";
return( 252, $msg );
}
It's the only place where $login_output is used in a "concatenation (.) or string" as described in the error message.
So the the call to $ssh->login() is failing in such a way as to leave $login_output undefined.
I don't know anything about Net::SSH::Expect, but I suspect that you need to change the arguments to the new() call (a few lines above) in some way.
You'll get more information about what has gone wrong by adding $# to the debug output.
The most likely candidate for that error is this:
my $login_output;
eval { $login_output = $ssh->login(); };
if( $# )
{
$msg = "Login has failed. Output: $login_output"; # this line
return( 252, $msg );
}
Remove $login_output from that line since it will be uninitialized if login() dies/croaks. You can replace it with $# to get the message supplied to die/croak.

My code to change the password from remote server is not working

I was using this in the perl script, where it is login to a couple of servers and trying to change the password for the servers through a remote host. But the problem is that the password is not getting changed on both the servers as well as i am not finding a way to check if the new passwords are passed to the servers using expect. i am posting that part of the code where it is checking for the prompt and trying to change the password.
#!/usr/bin/perl
package Session;
use strict;
use warnings;
use Expect;
use IO::Pty;
use Data::Dumper;
use Time::HiRes qw(usleep);
use Switch;
use YAML;
use feature 'say';
my $host1 = $ARGV[0];
my $host2 = $ARGV[1];
my $host1_adapter_name = $ARGV[2];
my $host2_adapter_name = $ARGV[3];
my $exp = Expect->new;
my ($selfObj) = #_;
my $str = "{$host1}\{root} # ";
my $cmdStr; my $result; my $dev_id;
my $timeout = 10;
my $min = 192;
my $range = 32;
my $host1_dev_id = _adapter($host1_adapter_name);
my $host2_dev_id = _adapter($host2_adapter_name);
my #hosts = ("$host1", "$host2");
print ("host2 name is=$host2------");
foreach my $n (#hosts)
{
print ("value of n is $n\n");
if ( $n eq $host1 )
{
_login($n,$host1_dev_id);
}
if ( $n eq $host2)
{
print ("inside 2nd if-----\n");
_login($n,$host2_dev_id);
}
}
sub _login
{
my ($host,$host_dev_id) = #_;
my $exit = 1;
$exp->raw_pty(1);
$exp = Expect->spawn("telnet $host") or die "unable to connect , Please check the connection & retry again: $!\n";
if (!defined($exp))
{
print "Please check the connection & retry again\n";
return -1;
}
`sleep 2 `;
$exp->expect($timeout,
[
qr'[lL]ogin:[\s]?[a]?[s]?[\s]?$',
sub
{
$exp->send("root\r");
`sleep 3 `;
exp_continue;
}
],
[
qr'[pP]assword:[\s]?$',
sub
{
$exp->send("That11NeverWork!\r");
exp_continue;
}
],
[
qr '[#>:][\s]?$',
sub {
$cmdStr = "passwd\r";
$result =_run_cmd($cmdStr);
qr'root\'s New password:\s*';
$exp->send("raym0nd24");
qr'Enter the new password again:\s*';
$exp->send("raym0nd24");
# $exp->send('passwd:\s*',5);
$exit = 0;
exp_continue;
}
],
[
eof =>
sub
{
print("FileName : Session.pm , ERROR: premature EOF in command execution.\n");
}
],
'-re', qr'[#$>:]\s?$', # wait for shell prompt, then exit expect
);
}
#############################################################
#############################################################################
sub _adapter
{
my ($adapter_name) = #_;
print "Adapter name: $adapter_name\n";
chomp($adapter_name);
switch($adapter_name){
case "AUSTIN" {$dev_id="e414571614102004"}
case "CX5" {$dev_id="b315191014103506"}
case "CX4" {$dev_id="b31513101410f704"}
case "CX4_EG10" {$dev_id="b315151014101f06"}
case "CX4_EG25" {$dev_id="b315151014101e06"}
case "CX3" {$dev_id="RoCE"}
case "CX2" {$dev_id="b315506714106104"}
case "CX3_PRO" {$dev_id="RoCE"}
case "CX3_PRO1" {$dev_id="b31507101410e704"}
case "HOUSTON_LR" {$dev_id="df1020e214104004"}
case "HOUSTON_SR" {$dev_id="df1020e214100f04"}
case "HOUSTON_Cu" {$dev_id="df1020e214103d04"}
case "SHINER_S" {$dev_id="e4148a1614109304"}
case "SHINER_T" {$dev_id="e4148e1614109204"}
case "SLATE_SR" {$dev_id="df1020e21410e304"}
case "SLATE_CU" {$dev_id="df1020e21410e404"}
case "EVERGLADES" {$dev_id="b315151014101e06"}
else { print "Adapter not in list\n"}
}
return $dev_id;
}
#######################################################################################
##########################################################
sub _run_cmd
{
my $output; my $output1;
my ($cmdStr) = #_;
$exp->send($cmdStr ."\r");
$exp->expect(21, '-re', $str);
$output = $exp->exp_before();
$exp->clear_accum();
my #PdAt_val = split("\r?\n", $output);
foreach my $line1 (#PdAt_val)
{
chomp($line1);
if ( $line1 =~ /(\(\d+\))(\s*root\s*\#\s*)/)
{
if ( $1 =~ /\((\d+)\)/)
{
if ($1 != 0)
{
print("*************** Command $cmdStr didn't ran sucessfully ***************\n");
exit;
}
}
}
}
return $output;
}
######################################################################
There are individual solutions for different systems. So some systems got from their god the must have highlevel restrictions. So the regular says, that you cant login as root directly. To step up the long way to the stage you can use sudo or su. I didnt see that mind in your lines.
# The simpliest way is to use what you have!
sub passwd
{
my $user = #_[0];
my $password = #_[1];
#
# as root
my $execline = qq~passwd $user:$password~;
#
# as root with second password
my $execline = qq~passwd $user:$password\n$password~;
#
# for microsoft certified ubuntu noobs, kidding mint's
my $execline = qq~sudo $password && passwd $user:$password~;
#
# for apple greyed, debian nerds, solaris freaks
my $execline = qq~su $password && passwd $user:$password~;
#
my $return = system("$execline");
}
print &passwd("root","the magical word");
#
# elseif read this.url([to get the higher experience][1]);
[1]: https://stackoverflow.com/questions/714915/using-the-passwd-command-from-within-a-shell-script

Azure REST API "Put Block" error 596?

I can't see any information in the Azure Blob Service Error Code list https://msdn.microsoft.com/en-us/library/dd179439.aspx that relates to error 596.
I am trying to upload some blocks to the Azure service and am getting a response back from the API with code 596 and description 'Broken pipe'.
Has anyone encountered this before ?
(N.B. Yes, I know the code below is not complete yet in that the code as-is does not upload the final chunk)
#!/usr/bin/perl
use 5.014;
use strict;
use warnings;
use autodie;
use Data::Dumper;
use Digest::MD5 qw(md5_base64);
use Crypt::PRNG::Fortuna qw(random_bytes_b64u random_bytes);
use Digest::SHA qw(hmac_sha256_base64);
use Getopt::Long;
use Sys::Syslog qw( :DEFAULT setlogsock);
use File::stat;
use AnyEvent;
use AnyEvent::HTTP;
use Time::Piece;
use Encode qw(decode encode);
use MIME::Base64 qw(encode_base64 decode_base64 encode_base64url);
use FileHandle;
use Fcntl ':flock', 'SEEK_SET';
delete #ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
use sigtrap 'handler' => \&term_handler, 'normal-signals';
####### PARAMS
my $script="upload.pl";
my $maxSingleUpload=1048576; # Maximum size of a single attempt upload (in bytes);
my $multiChunkSize=4194304; # Maximum size of a single block (in bytes)
my $multiLimit=6; # Maximum number of parallel HTTP requests
####### AZURE
my $azureKey="<REMOVED>";
my $azureKeyBin=decode_base64($azureKey);
####### ARGS
my ($vault,$container,$localfile,$remotefile);
my $debug=0;
GetOptions(
"vault|v=s" => \$vault,
"container|c=s" => \$container,
"localfile|l=s" => \$localfile,
"remotefile|r=s" => \$remotefile,
"debug|d+" => \$debug
);
if (!defined $vault || !defined $container || !defined $localfile || !defined $remotefile) {
say "USAGE: -v <vault> -c <container> -l <localfile> -r <remotefile> [-d (debug)]";
exit 1;
}
if (!-e $localfile) {
say "Local file does not exist !";
exit 1;
}
####### Vars
my ($wholeChunks,$chunkRemainder,$runID,$condvar,#offsets,#blocklist);
my $activeCount=0;
my $putBlockURL="https://${vault}.blob.core.windows.net/${container}/${remotefile}?comp=block&blockid=";
####### FUNCTIONS
# Quotient remainder calculator
sub qrem {
use integer;
my( $dividend, $divisor ) = #_;
my $quotient = $dividend / $divisor;
my $remainder = $dividend % $divisor;
my #result = ( $quotient, $remainder );
return #result;
}
# Do pad
sub doPad {
my ($raw) = #_;
while (length($raw) % 4) {
$raw .= '=';
}
return $raw;
}
# Random
sub getRandom {
my ($len) = #_;
#return doPad(random_bytes_b64u($len));
return doPad(encode_base64(random_bytes($len)));
}
# Term handler
sub term_handler {
doLog("err","term_handler: Program terminated early due to user input");
exit 2;
}
# Log sub
sub doLog {
my ($priority,$msg) = #_;
return 0 unless ($priority =~ /info|err|debug/);
setlogsock('unix');
openlog($script, 'pid,cons', 'user');
syslog($priority, $msg);
closelog();
return 1;
}
# Get file size
sub fileSz {
my($file) = #_;
my $stat = stat($file);
return $stat->size;
}
# Get data
sub readData {
my ($file,$length,$offset)=#_;
my $fh = FileHandle->new;
my ($data);
if ($debug) { say "Reading ${file} offset ${offset} for length ${length}";}
#open ($fh,"<",$file);
$fh->open("< $file");
binmode($fh);
seek($fh,$offset,SEEK_SET);
read($fh,$data,$length);
if ($debug) { say "readData read ".byteSize($data);}
#close($fh);
$fh->close;
return $data;
}
# Calc MD5
sub calcMD5 {
my ($data)=#_;
my $hash = md5_base64($data);
return doPad($hash);
}
# Populate offsets
sub populateOffsets {
my ($count,$offsetSize)=#_;
if (!defined $count || !defined $offsetSize) {exit 1;}
my $offset=0;
my #offsets;
for my $i (1..$count) {
push #offsets,$offset;
$offset = $offset + $offsetSize;
}
return #offsets;
}
# Calc auth string
sub azureAuth {
my($t,$signstring)=#_;
if (!defined $signstring) { exit 1;}
if ($debug) {say "String to sign:${signstring}";}
my $auth;
$auth=doPad(hmac_sha256_base64($signstring,$azureKeyBin));
if ($debug) { say "Sig:${auth}";}
return $auth;
}
# Byte size
sub byteSize {
use bytes;
my ($inval)=#_;
return length($inval);
}
# Process
sub doProcess {
return if $activeCount >= $multiLimit;
my $offset = shift #offsets;
return if !defined $offset;
$activeCount++;
if ($debug) { say "Active:${activeCount}, Offset:${offset}";}
$condvar->begin;
my $t = localtime;
my $tNow = $t->strftime();
my $blockid = getRandom(8);
my $subRunID=getRandom(5);
my $contentLength=$multiChunkSize-1;
my $content = readData($localfile,$contentLength,$offset);
my $hash = calcMD5($content);
if ($debug) { say "Block ID:${blockid}, Hash: ${hash}";}
my $url = $putBlockURL.$blockid;
my $canocResource="/${vault}/${container}/${remotefile}\nblockid:${blockid}\ncomp:block";
my $hdrs="x-ms-client-request-id:${runID}\nx-ms-date:${tNow}\nx-ms-version:2009-09-19";
my $byteLength=byteSize(${content});
my $canocHeaders=encode('UTF-8',"PUT\n\n\n${byteLength}\n${hash}\n\n\n\n\n\n\n\n${hdrs}\n${canocResource}",Encode::FB_CROAK);
my $authData=azureAuth($t,$canocHeaders);
if ($debug) {say "Length:${byteLength}";say "Sig: ${authData}"; say "URL:${url}";}
my $azureArr = {
"Authorization"=>"SharedKey ${vault}:${authData}",
"Content-Length"=>${byteLength},
"Content-MD5"=>${hash},
"x-ms-version"=>"2009-09-19",
"x-ms-date"=>${tNow},
"x-ms-client-request-id"=>"${runID}"
};
####### ERROR OCCURS HERE ....
http_request "PUT" => $url,
persistent=>0,
headers=>$azureArr,
body=>$content,
sub {
my ($body, $hdr) = #_;
say Dumper($hdr);
#say "received, Size: ", length $body;
#say $body;
$activeCount--;
$condvar->end;
doProcess();
};
return 1;
}
####### MAIN
$runID=getRandom(5);
doLog("info","${runID} Starting upload for ${localfile} (${remotefile})");
if (fileSz($localfile)<$maxSingleUpload) {
if ($debug) {say "Using single upload method";}
} else {
if ($debug) {say "Using multi-upload method";}
# Calculate chunk quantity
my #chunks = qrem(fileSz($localfile),$multiChunkSize);
$wholeChunks=$chunks[0];
$chunkRemainder=$chunks[1];
if ($debug) {say "Whole chunks (${multiChunkSize}):${wholeChunks}, Remainder:${chunkRemainder}";}
# Init
#offsets=populateOffsets(${wholeChunks},${multiChunkSize});
say Dumper(#offsets);
$condvar = AnyEvent->condvar;
# DO IT
for (1..$multiLimit) {
doProcess();
}
$condvar->recv;
}
doLog("info","${runID} Upload complete");
exit 0;
Error 596 is a client-side error returned by AnyEvent::HTTP. You need to investigate locally to see why you are hitting this error.
See this page for more info:
https://metacpan.org/pod/AnyEvent::HTTP
596 - errors during TLS negotiation, request sending and header processing.

TCP Server multiple receive and respond

Im trying to emulate a TCP Server on the same PC where the app is running.
I dont know if it can be done in Perl because im not very experienced.
With the code bellow the first reply is working but i dont know how to implement the second.
#!/usr/bin/perl -w
use IO::Socket::INET;
use strict;
my $socket = IO::Socket::INET->new('LocalPort' => '3000',
'Proto' => 'tcp',
'Listen' => SOMAXCONN)
or die "Can't create socket ($!)\n";
print "Server listening\n";
while (my $client = $socket->accept) {
my $name = gethostbyaddr($client->peeraddr, AF_INET);
my $port = $client->peerport;
while (<$client>) {
print "$_";
print $client "RESPONSE1";
}
close $client
or die "Can't close ($!)\n";
}
die "Can't accept socket ($!)\n";
EDIT: Thank you guys for the imput, i ended up with php done it and its working, yay!
Use Net::Server for the connection, and a variable in the sub to keep the current state ($state in this code); something like this:
package MyServer;
use base qw/Net::Server/;
use strict;
use warnings;
sub process_request {
my $self = shift;
my $state = 0;
while (<STDIN>) {
s/\r?\n$//; # like chomp but for crlf too
if ($state == 0 and $_ eq 'data1') {
print "> okay1\n";
$state++;
} elsif ($state == 1 and $_ eq 'data2') {
print "> okay2\n";
$state++;
} else {
last if $state == 2;
$state = 0;
}
}
}
my $port = shift || 3000;
MyServer->run( port => $port );
The example in the Net::Server POD suggests using an alarm to timeout connections, which might be appropriate here. The code above does the following:
$ nc localhost 3000
data1
> okay1
data2
> okay2
data3
$
And if you need to move to a forking / preforking / non-blocking / co-routine driven system, there's a Net::Server personality for that.
"ready to go" code:
package MyServer;
use base qw/Net::Server/;
use strict;
use warnings;
sub process_request {
my $self = shift;
my $state = 0;
$| = 1;
binmode *STDIN;
while (read(*STDIN, local $_, 3 )) {
if ($state == 0 and $_ eq "\x{de}\x{c0}\x{ad}") {
print "\x{c4}\x{1a}\x{20}\x{de}";
$state++;
} elsif ($state == 1 and $_ eq "\x{18}\x{c0}\x{0a}") {
print "\x{11}\x{01}\x{73}\x{93}";
$state++;
last;
}
}
}
my $port = shift || 3000;
MyServer->run( port => $port );
It seems to me process_request sub doesn't work correctly when a low port is set (in my situation, port 23). In particular only with low port, while parsing data input, the first request contains additional chars (but it's all ok with subsequent requests).
Have you a tips? Thank you

mib name printing from mib values in perl

This is the code that I used to walk through the table in net:snmp using perl:
#! /usr/local/bin/perl
use strict;
use warnings;
use Net::SNMP qw(:snmp);
my $OID_hrSystem = '1.3.6.1.2.1.25.1';
my $OID_ifPhysAddress = '1.3.6.1.2.1.2.2.1.6';
my ($session, $error) = Net::SNMP->session(
-hostname => shift || 'localhost',
-community => shift || 'public',
-nonblocking => 1,
-translate => [-octetstring => 0],
-version => 'snmpv2c',
);
if (!defined $session) {
printf "ERROR: %s.\n", $error;
exit 1;
}
my %table; # Hash to store the results
my $result = $session->get_bulk_request(
-varbindlist => [ $OID_hrSystem ],
-callback => [ \&table_callback, \%table ],
-maxrepetitions => 10,
);
if (!defined $result) {
printf "ERROR: %s\n", $session->error();
$session->close();
exit 1;
}
# Now initiate the SNMP message exchange.
snmp_dispatcher();
$session->close();
# Print the results, specifically formatting ifPhysAddress.
for my $oid (oid_lex_sort(keys %table)) {
if (!oid_base_match($OID_ifPhysAddress, $oid)) {
printf "%s = %s\n", $oid, $table{$oid};
} else {
printf "%s = %s\n", $oid, unpack 'H*', $table{$oid};
}
}
exit 0;
sub table_callback
{
my ($session, $table) = #_;
my $list = $session->var_bind_list();
if (!defined $list) {
printf "ERROR: %s\n", $session->error();
return;
}
# Loop through each of the OIDs in the response and assign
# the key/value pairs to the reference that was passed with
# the callback. Make sure that we are still in the table
# before assigning the key/values.
my #names = $session->var_bind_names();
my $next = undef;
while (#names) {
$next = shift #names;
if (!oid_base_match($OID_hrSystem, $next)) {
return; # Table is done. chakri
}
$table->{$next} = $list->{$next};
}
# Table is not done, send another request, starting at the last
# OBJECT IDENTIFIER in the response. No need to include the
# calback argument, the same callback that was specified for the
# original request will be used.
my $result = $session->get_bulk_request(
-varbindlist => [ $next ],
-maxrepetitions => 10,
);
if (!defined $result) {
printf "ERROR: %s.\n", $session->error();
}
return;
}
Output is:
1.3.6.1.2.1.25.1.1.0 = 1 hour, 12:00.77
1.3.6.1.2.1.25.1.2.0 = �
+
1.3.6.1.2.1.25.1.3.0 = 1536
1.3.6.1.2.1.25.1.4.0 = BOOT_IMAGE=/boot/vmlinuz-3.0.0-14-generic root=UUID=5c4c8d22-3cea-4410-aaad-f297c75d217e ro quiet splash vt.handoff=7
1.3.6.1.2.1.25.1.5.0 = 1
1.3.6.1.2.1.25.1.6.0 = 133
1.3.6.1.2.1.25.1.7.0 = 0
But the required output for me is as follows:
hrSystemUptime.0 = 1:08:54.36
hrSystemDate.0 = 2011-12-14,16:0:2.0,+1:0
hrSystemInitialLoadDevice.0 = 1536
hrSystemInitialLoadParameters.0 = "BOOT_IMAGE=/boot/vmlinuz-3.0.0-14-generic root=UUID=5c4c8d22-3cea-4410-aaad-f297c75d217e ro quiet splash vt.handoff=7"
hrSystemNumUsers.0 = 1
hrSystemProcesses.0 = 133
hrSystemMaxProcesses.0 = 0
The main thing in the output is I want mib names to be printed in the output instead of the mib values
You could use the SNMP module (available on Ubuntu as libsnmp-perl) which offers a tied hash to loaded MIBs, %SNMP::MIB. Here's some example code:
use SNMP;
SNMP::initMib();
print "$SNMP::MIB{'1.3.6.1.2.1.25.1.1.0'}{label} = \n";
#Should print "hrSystemUptime = "
Because %SNMP::MIB is a tied hash, you can't just do a lookup and assign to a lexical variable, i.e. my $oid = $SNMP::MIB{$oidstr}. You have to access it directly every time.
There is lots of other information that it loads from the MIB, including data type, which could help with the issue it looks like you have with hrSystemDate. Also, see the man page for mib_api if you need to load specific MIBs. The ones you used in your example loaded by default on my system, though.
have you tried the snmpget command on your server? When I run snmpget direcly on CLI, the result cames with the name:
Ex: /usr/local/bin/snmpget -O Q -v 2c -c Community x.x.x.x .1.3.6.1.2.1.31.1.1.1.6.100663301
IF-MIB::ifHCInOctets.100663301 = 152528664859348
If it works for you, you might want to exectute the command in the PERL code, instead of using the LIB. Then you just have to handle with the output.
Also, tou can use snmptranslate to tranlate your OIDs:
Ex: /usr/local/bin/snmptranslate 1.3.6.1.2.1.25.1.1
HOST-RESOURCES-MIB::hrSystemUptime
More Info -> http://www.net-snmp.org/wiki/index.php/TUT:snmptranslate
EDIT
Why don't you:
my $pathSnmpTranslate = '/your/path/to/snmptranslate';
for my $oid (oid_lex_sort(keys %table)) {
my $oidTrans = `$pathSnmpTranslate $oid`;
if (!oid_base_match($OID_ifPhysAddress, $oid)) {
printf "%s = %s\n", $oidTrans, $table{$oid};
} else {
printf "%s = %s\n", $oidTrans, unpack 'H*',$table{$oid};
}
}
On my machine it worked:
> /xxx % /usr/local/bin/snmptranslate 1.3.6.1.2.1.25.1.1
HOST-RESOURCES-MIB::hrSystemUptime
> /xxx % /usr/local/bin/snmptranslate 1.3.6.1.2.1.25.1.1.0
HOST-RESOURCES-MIB::hrSystemUptime.0