I am running some commands in a remote server by connecting from my local server. To achieve this I am connecting to remote server using Net::SSH::Expect perl module. Connection is establishing here, but sometimes when I execute the command the following error comes up -
Can't call method "send" on an undefined value at .....
Here is my code:
my ($ip, $user, $passwd) = ("my.ip.address.here","user", "password");
my $ssh = SSH_Connection( $ip, $user, $passwd );
my $command_to_execute = "<Command to be executed will build here>";
print "$command_to_execute\n";
$str = 'Bye';
$ssh->send("$command_to_execute; echo $str");
$output = $ssh->waitfor($str, undef);
$ssh->close();
print "END\n";
sub SSH_Connection {
my ( $host, $user, $passwd ) = #_;
my $ssh = Net::SSH::Expect->new (
host => $host, #ip
user => $user, #'user'
password => $passwd, #'password'
raw_pty => 1,
no_terminal => 0,
);
my $login_output;
my $handledie = eval {
$login_output = $ssh->login();
};
if ( $# ) {
if ($# =~ m/SSHConnectionError/i ) {
print "SSH Connection Error\n";
} elsif ( $# =~ m/SSHProcessError/ix ) {
print "SSH Process Error\n";
} elsif ( $# =~ m/SSHConnectionAborted/ix ) {
print "SSH Connection Aborted\n";
} else {
print "SSH Unknown Error: $#\n";
}
}
if ($login_output !~ /Last login/) {
die "Login has failed.";
} else {
return $ssh;
}
print "SSH to ip - $host failed\n";
}
First I'm building the command and storing it in $command_to_execute variable.
At the end of command execution I'll get keyword Bye. So I am waiting for that keyword to match.
My question is -
Why I am getting above mentioned error?
Suppose if my command execution is failed, will the control will come back to my script ? Because its waiting for $str word.
I doubt about the error catching method is not proper. Please suggest a better solution.
I have created a perl that telnet to multiple switches. I would like to check if telnet functions properly by telneting the switch.
This is my code to telnet to the switches:
#!/usr/bin/perl
use warnings;
use Net::Cisco;
open( OUTPUT, ">log.txt" );
open( SWITCHIP, "ip.txt" ) or die "couldn't open ip.txt";
my $count = 0;
while (<SWITCHIP>) {
chomp($_);
my $switch = $_;
my $tl = 0;
my $t = Net::Telnet::Cisco->new(
Host => $switch,
Prompt =>
'/(?m:^(?:[\w.\/]+\:)?[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$)/',
Timeout => 5,
Errmode => 'return'
) or $tl = 1;
my #output = ();
if ( $tl != 1 ) {
print "$switch Telnet success\n";
}
else {
my $telnetstat = "Telnet Failed";
print "$switch $telnetstat\n";
}
close(OUTPUT);
$count++;
}
This is my output status after I was testing 7 switches:
10.xxx.3.17 Telnet success
10.xxx.10.12 Telnet success
10.xxx.136.10 Telnet success
10.xxx.136.12 Telnet success
10.xxx.188.188 Telnet Failed
10.xxx.136.13 Telnet success
I would like to convert the telnet result as log file.
How to separate successful and failed telnet results by using perl?
Please Try the following
#!/usr/bin/perl
use warnings;
use Net::Cisco;
################################### S
open( OUTPUTS, ">log_Success.txt" );
open( OUTPUTF, ">log_Fail.txt" );
################################### E
open( SWITCHIP, "ip.txt" ) or die "couldn't open ip.txt";
my $count = 0;
while (<SWITCHIP>) {
chomp($_);
my $switch = $_;
my $tl = 0;
my $t = Net::Telnet::Cisco->new(
Host => $switch,
Prompt =>
'/(?m:^(?:[\w.\/]+\:)?[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$)/',
Timeout => 5,
Errmode => 'return'
) or $tl = 1;
my #output = ();
################################### S
if ( $tl != 1 ) {
print "$switch Telnet success\n"; # for printing it in screen
print OUTPUTS "$switch Telnet success\n"; # it will print it in the log_Success.txt
}
else {
my $telnetstat = "Telnet Failed";
print "$switch $telnetstat\n"; # for printing it in screen
print OUTPUTF "$switch $telnetstat\n"; # it will print it in the log_Fail.txt
}
################################### E
$count++;
}
################################### S
close(SWITCHIP);
close(OUTPUTS);
close(OUTPUTF);
################################### E
In print statement after print just write the filehandle name which is OUTPUT in your code:
print OUTPUT "$switch Telnet success\n";
and
print OUTPUT "$switch $telnetstat\n";
A side note: always use a lexical filehandle and three arguments with error handling to open a file. This line open(OUTPUT, ">log.txt"); you can write like this:
open my $fhout, ">", "log.txt" or die $!;
Use Sys::Syslog to write log messages.
But since you're opening a log.txt file with the handle OUTPUT, just change your two print statements to have OUTPUT as the first argument and the string as the next (without a comma).
my $telnetstat;
if($tl != 1) {
$telnetstat = "Telnet success";
} else {
$telnetstat = "Telnet Failed";
}
print OUTPUT "$switch $telnetstat\n";
# Or the shorter ternary operator line for all the above:
print OUTPUT $swtich . (!$tl ? " Telnet success\n" : " Telnet failed\n");
You might consider moving close to an END block:
END {
close(OUTPUT);
}
Not only because it's in your while loop.
I am having two huge .csv files one is around 8 GB and other is 3.4 GB file size. I want only few values from each line inside that .csv files.
Its taking huge time to modify the data and copy it into new file.
Could anyone help in modifying the code.So that the modification will be completed in a reasonable time.
Below is the lines of code:
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV;
require "$ENV{'SAI_HOME'}/bin/utils/Logging.pl";
require "$ENV{'SAI_HOME'}/bin/utils/Utilities.pl";
my $date1 = `date '+%d-%m-%Y_%H-%M-%Ss'`;
chomp($date1);
our $LOGPATH = "$ENV{'SAI_HOME'}/logs/SP6migrationcsv_$date1.log";
my $status = 0;
log_info("Refer $LOGPATH log file for more information");
my $csv = Text::CSV->new( { binary => 1, eol => $/, sep_char => ',' } );
my $file1 = $ARGV[0] or die "Please provide Subscriber and Subscription CSV files on the command line\n";
my $file2 = $ARGV[1] or die "Please provide Subscriber and Subscription CSV files on the command line\n";
my $subscriberFile = "";
my $subscriptionFile = "";
if ( ( grep /SUBSCRIBER/i, $file1 ) && ( grep /SUBSCRIPTION/i, $file2 ) ) {
$subscriberFile = $file1;
$subscriptionFile = $file2;
} elsif ( ( grep /SUBSCRIBER/i, $file2 ) && ( grep /SUBSCRIPTION/i, $file1 ) ) {
$subscriptionFile = $file1;
$subscriberFile = $file2;
} else {
log_error("Invalid CSV files input");
exit -1;
}
my $SP6DIR = `dirname $0`;
chomp $SP6DIR;
$SP6DIR = "${SP6DIR}/SP6";
`mkdir -p $SP6DIR` or checkExit( $?, "Unable to carete $SP6DIR directory" );
my $newSubscriberFile = "Subscriber.csv";
my $newSubscriptionFile = "Subscription.csv";
my $subscriptionimsifile = "$SP6DIR/.IMSI_$newSubscriptionFile";
my $subscriberimsifile = "$SP6DIR/.IMSI_$newSubscriberFile";
$newSubscriberFile = "${SP6DIR}/$newSubscriberFile";
$newSubscriptionFile = "${SP6DIR}/$newSubscriptionFile";
`dos2unix $subscriptionFile $subscriberFile 2>/dev/null`
or checkExit( $?, "Unable to perform dos2unix on input files" );
`cut -d "," -f3 $subscriptionFile > $subscriptionimsifile`
or checkExit( $?, "Failed to get IMSI details from $subscriptionFile" );
`cut -d "," -f1 $subscriberFile > $subscriberimsifile`
or checkExit( $?, "Failed to get IMSI details from $subscriberFile" );
my $isSubscriptionHeaderPresesnt = "false";
my $isSubscriberHeaderPresesnt = "false";
$status = system("head -1 $subscriptionimsifile | grep 'IMSI' >>/dev/null");
if ( $status == 0 ) {
$isSubscriptionHeaderPresesnt = "true";
}
$status = system("head -1 $subscriberimsifile | grep 'IMSI' >>/dev/null");
if ( $status == 0 ) {
$isSubscriberHeaderPresesnt = "true";
}
open( my $subscriptionData, '<:encoding(utf8)', $subscriptionFile )
or die "Could not open '$subscriptionFile' $!\n";
open( NEWSUBSCRIBERDATA, "> $newSubscriberFile" ) or die "Could not open '$newSubscriberFile' $!\n";
open( NEWSUBSCRIPTIONDATA, "> $newSubscriptionFile" ) or die "Could not open '$newSubscriptionFile' $!\n";
if ( "$isSubscriptionHeaderPresesnt" eq "true" ) {
my $subscriptionHeader = <$subscriptionData>;
if ( $csv->parse($subscriptionHeader) ) {
my #subscriptionHeaderFields = $csv->fields();
print NEWSUBSCRIPTIONDATA "\"$subscriptionHeaderFields[0]\",\"$subscriptionHeaderFields[2]\",\"$subscriptionHeaderFields[4]\",\"$subscriptionHeaderFields[5]\",\"$subscriptionHeaderFields[6]\",\"$subscriptionHeaderFields[8]\",\"$subscriptionHeaderFields[13]\",\"$subscriptionHeaderFields[14]\",\"$subscriptionHeaderFields[15]\",\"$subscriptionHeaderFields[16]\",\"$subscriptionHeaderFields[17]\",\"$subscriptionHeaderFields[18]\",\"$subscriptionHeaderFields[25]\",\"$subscriptionHeaderFields[26]\",\"$subscriptionHeaderFields[27]\"\n";
print NEWSUBSCRIBERDATA "\"IMSI\",\"IMEI\",\"MSISDN\",\"$subscriptionHeaderFields[21]\",\"$subscriptionHeaderFields[22]\",\"$subscriptionHeaderFields[12]\",\"$subscriptionHeaderFields[9]\",\"$subscriptionHeaderFields[1]\",\"$subscriptionHeaderFields[0]\"\n";
} else {
log_error("Line could not be parsed: $subscriptionHeader\n");
exit 1;
}
} else {
log_only("No header info in subscription file");
}
if ( "$isSubscriptionHeaderPresesnt" eq "false" && "$isSubscriberHeaderPresesnt" eq "true" ) {
print NEWSUBSCRIBERDATA "\"IMSI\",\"IMEI\",\"MSISDN\",\"CUSTOMER_SEGMENTATION\",\"CUST_SUBCATEGORY\",\"SUBS_TYPE\",\"SUBSCRIPTION_PLAN\",\"CONTRACT_IDREF\",\"SUBSCRIPTION_IDREF\"\n";
} else {
log_only("No header info in subscriber file");
}
my $subscriberHeader = "";
my #subscriptionFields = {};
my #subscriberFields = {};
while ( my $eachSubscriptionLine = <$subscriptionData> ) {
chomp $eachSubscriptionLine;
if ( $csv->parse($eachSubscriptionLine) ) {
#subscriptionFields = $csv->fields();
$status = system("grep \"^[\\\"]*${subscriptionFields[2]}[\\\"]*\\\$\" $subscriberimsifile >> /dev/null");
if ( $status == 0 ) {
my $lastMatchedSubscriberdata = `grep "^[\\\"]*${subscriptionFields[2]}[\\\"]*," $subscriberFile | tail -1`;
chomp $lastMatchedSubscriberdata;
if ( $csv->parse($lastMatchedSubscriberdata) ) {
#subscriberFields = $csv->fields();
if ( "${subscriberFields[0]}" eq "${subscriptionFields[2]}" ) {
#log_only("Updating \"#subscriberFields\" subscriber details from subscription data");
print NEWSUBSCRIBERDATA "\"$subscriberFields[0]\",\"$subscriberFields[1]\",\"$subscriptionFields[2]\",\"$subscriptionFields[21]\",\"$subscriptionFields[22]\",\"$subscriptionFields[12]\",\"$subscriptionFields[9]\",\"$subscriptionFields[1]\",\"$subscriptionFields[0]\"\n";
} else {
log_error("Unable to process #subscriberFields record");
exit -1;
}
} else {
log_error("Line could not be parsed: $lastMatchedSubscriberdata\n");
exit 1;
}
} else {
log_only("Adding new subscriber details from subscription : \"#subscriptionFields\"");
print NEWSUBSCRIBERDATA "\"$subscriptionFields[2]\",,\"$subscriptionFields[3]\",\"$subscriptionFields[21]\",\"$subscriptionFields[22]\",\"$subscriptionFields[12]\",\"$subscriptionFields[9]\",\"$subscriptionFields[1]\",\"$subscriptionFields[0]\"\n";
}
print NEWSUBSCRIPTIONDATA "\"$subscriptionFields[0]\",\"$subscriptionFields[2]\",\"$subscriptionFields[4]\",\"$subscriptionFields[5]\",\"$subscriptionFields[6]\",\"$subscriptionFields[8]\",\"$subscriptionFields[13]\",\"$subscriptionFields[14]\",\"$subscriptionFields[15]\",\"$subscriptionFields[16]\",\"$subscriptionFields[17]\",\"$subscriptionFields[18]\",\"$subscriptionFields[25]\",\"$subscriptionFields[26]\",\"$subscriptionFields[27]\"\n";
} else {
log_error("Line could not be parsed: $eachSubscriptionLine\n");
exit 1;
}
}
close(NEWSUBSCRIPTIONDATA);
open( my $subscriberData, '<:encoding(utf8)', $subscriberFile ) || die "Could not open '$subscriberFile' $!\n";
if ( "$isSubscriberHeaderPresesnt" eq "true" ) {
$subscriberHeader = <$subscriberData>;
}
while ( my $eachSubscriberLine = <$subscriberData> ) {
chomp $eachSubscriberLine;
if ( $csv->parse($eachSubscriberLine) ) {
#subscriberFields = $csv->fields();
$status = system("grep \"^[\\\"]*${subscriberFields[0]}[\\\"]*\\\$\" $subscriptionimsifile >>/dev/null");
if ( $status != 0 ) {
log_only(
"Adding back subscriber details, because unable to get IMSI details from subscription file : \"#subscriberFields\""
);
print NEWSUBSCRIBERDATA "\"$subscriberFields[0]\",\"$subscriberFields[1]\",\"$subscriberFields[2]\",\"$subscriberFields[6]\",,\"$subscriberFields[7]\",,,\n";
}
} else {
log_error("Line could not be parsed: $eachSubscriberLine\n");
exit 1;
}
}
close(NEWSUBSCRIBERDATA);
`sed -i -e '1 s|SUBSCRIPTION_ID|SUBSCRIPTION_IDREF|g' -e '1 s|SUBS_CATEGORY|SUBSCRIPTION_PLAN|g' -e '1 s|SUBS_STATE|SUBS_TYPE|g' -e '1 s|CUST_CATEGORY|CUSTOMER_SEGMENTATION|g' $newSubscriberFile`
or checkExit( $?, "Unable to update header info in subscriber fi le" );
General advice:
Don't use backticks to parse your input. Perl is perfectly capable of doing this with a while loop and split.
Misspelling variable names is going to screw you. Don't. isSubscriptionHeaderPresesnt
mixing your open calls - 3 argument with lexicals is generally preferred, but mismatching isn't nice.
Using the text string "false" in lieu of a boolean is horrible. Don't do it. Someone someday is going to do the equivalent of print "true" if "false" and it's going to break.
The most 'expensive' operation your script will be doing is reading the files. That's almost always true. So find something other than syscalls to grep or sed require full-rereading of the files you're targeting. Assuming subscriptionFile and subscriberFile are your biggies, you're reading them multiple times - you're running a cut that reads the whole thing. A dos2unix that reads the whole thing. A grep that reads the whole thing. And then you're opening it, and reading the whole thing.
your last line is a sed which will... re-read your output file, entirely, and apply a line by line transform to it.
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();
Suddenly, one server cannot be backed up. i get a strange error message:
2011-01-04 10:10:37 host1: Can't fork at /usr/share/backuppc/lib/BackupPC/Lib.pm line 1128.
What does this error mean?
All other hosts (with same OS) don't have this problem.
Thanks in advance for any reply. :)
$cmd = [split(/\s+/, $cmd)] if ( ref($cmd) ne "ARRAY" );
print(STDERR "cmdSystemOrEval: about to system ",
$bpc->execCmd2ShellCmd(#$cmd), "\n")
if ( $bpc->{verbose} );
if ( !defined($pid = open(CHILD, "-|")) ) { # <<<<<<<<< 1128
my $err = "Can't fork to run #$cmd\n";
$? = 1;
$$stdoutCB .= $err if ( ref($stdoutCB) eq 'SCALAR' );
&$stdoutCB($err) if ( ref($stdoutCB) eq 'CODE' );
return $err if ( !defined($stdoutCB) );
return;
}
binmode(CHILD);
if ( !$pid ) {
#
# This is the child
#
close(STDERR);
if ( $ignoreStderr ) {
open(STDERR, ">", "/dev/null");
} else {
open(STDERR, ">&STDOUT");
}
alarm(0);
$cmd = [map { m/(.*)/ } #$cmd]; # untaint
#
# force list-form of exec(), ie: no shell even for 1 arg
#
exec { $cmd->[0] } #$cmd;
print(STDERR "Exec of #$cmd failed\n");
exit(1);
}
The error message given at the top does not match the error message given in the code for some reason.
The error message lacks reporting $ERRNO. See fork(2) for the modes of failure for this system call.
Improve error reporting, then you need not guess about the cause.