Perl Net::SSH2::Cisco timeout on read when sending cmd() to switch - perl

Basically I have Cisco and Dell switches that I am trying to access using Net::SSH2::Cisco but I am getting a weird timeout error. Here is the code that is running:
$swConn = Net::SSH2::Cisco->new(Host => "$switchname.something", Prompt => '/' . $switch .'#/') or push(#skipFailedSwitches, $switch);
##############################################################################
# Changes for Cisco Nexus 5020 Switch start here
#
# Included the code for varying the password depending on switch
##############################################################################
$password = #mypassword;
print "logging into $switchname.something with username $username and password $password \n"; #SBW
if (not $swConn->login($username, $password)){
push(#skipFailedSwitches, $switch);
next;
}
#$swConn->login(Password => #mypassword);
#$fh = $swConn->input_log();
##############################################################################
# Changes for Cisco Nexus 5020 Switch end here
#
##############################################################################
$swConn->cmd('terminal length 0') or push(#skipFailedSwitches, $switch);
my #statusOut = $swConn->cmd('show interface status') or push(#skipFailedSwitches, $switch);
This gives me
timed-out during read at ./etherShine.pl line 172
Line 172 is
$swConn->cmd('terminal length 0') or push(#skipFailedSwitches, $switch);

Related

While SSH'ing following error occures - unable to establish master SSH connection: master process exited unexpectedly

I have a script which does ssh to number of servers (#alive_hosts) stored in an array and executes certain commands on those hosts (these hosts are IP address).
...
use Net::Ping;
use Net::OpenSSH;
use Parallel::ForkManager;
#these hosts are the IP addresses
my #hosts = ("host1", "host2", "host3", "host4", "host5");
my $p = Net::Ping->new();
foreach my $hostname (#hosts){
my ($ret, $duration, $ip) = $p->ping($hostname);
push (#alive_hosts, $hostname) if $ret;
}
my $ssh;
my $command = "perl -e "print \"Hello..\"";
my $pm = Parallel::ForkManager->new(5);
LOOP:
foreach my $n (#alive_hosts) {
my $pid = $pm->start and next LOOP;
#doing ssh to the host and running the command
#lets say here I am executing simple Perl command
$ssh = Connect($n, "user", "passwd");
$ssh->capture($command);
$pm->finish;
}
$pm->wait_all_children;
undef $ssh;
sub Connect {
my ( $host, $user, $passwd ) = #_;
my $ssh = Net::OpenSSH->new($host, user=>$user, password=>$passwd);
$ssh->error and die "Couldn't establish SSH connection: " . $ssh->error;
return $ssh;
}
...
When I execute this script, I am getting below error after certain time.
Warning: Permanently added 'host5' (RSA) to the list of known hosts.
Couldn't establish SSH connection: unable to establish master SSH connection: master process exited unexpectedly at script.pl ....
Actually $command is able to run in host1 to host4. But when it takes host5, its unable to run it.
I could able to ping host5 and connecting looks fine to me. But through the script it always fails to execute the command.
I have tried putting master_opts => [-o => "StrictHostKeyChecking=no", '-vvv'] in $ssh object in Connect() subroutine.
In capture, I added timeout period like this - $ssh->capture({timeout = 10}, $command);
But didn't succeeded in both the cases.
ssh version: OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013
Any idea why it's failing to run command in last host always?

Parallel::ForkManager gives - child process STDIN is not a real system Error

I have a script which does ssh to number if servers(#hosts) stored in an array and executes certain commands on those hosts.
...
use Net::OpenSSH;
use Parallel::ForkManager;
#these hosts are the IP addresses
my #hosts = ("host1", "host2", "host3", "host4", "host5");
my $ssh;
my $command = "perl -e "print \"Hello..\"";
my $pm = Parallel::ForkManager->new(5);
LOOP:
foreach my $n (#hosts) {
my $pid = $pm->start and next LOOP;
#doing ssh to the host and running the command
#lets say here I am executing simple Perl command
$ssh = Connect($n, "user", "passwd");
$ssh->capture($command);
$pm->finish;
}
$pm->wait_all_children;
undef $ssh;
sub Connect {
my ( $host, $user, $passwd ) = #_;
my $ssh = Net::OpenSSH->new($host, user=>$user, password=>$passwd);
$ssh->error and die "Couldn't establish SSH connection: " . $ssh->error;
return $ssh;
}
...
When I execute this script, I am getting below error which is like nightmare to me.
child process STDIN is not a real system file handle at (eval 2) line 145
I don't why this error occurs. Could someone please help me to resolve this issue.
Am I missing something in $pm->finish or do I need to add $pm->run_on_finish(..) ?

Unknown reason for Known error in the perl script

I am writing following script to read list of servers from the text file them ssh to them and run ldd command to fetch the version that is installed on the server.
The only problem is the error that I am seeing following error which says Bad Host name:
adev#abclnxdev:[/home/adev/perl-scripts] {63} % perl try.pl
Net::SSH: Bad host name: abclnxtest01
at try.pl line 21
when I manually do the ssh to this host. It gets connect.
Here is script :
#!/mu/bin/perl
use Net::SSH::Perl;
use warnings;
my $file = "server-list.txt";
my $usr = "user";
my $pwd = "password";
my $output_file = "GlibC-version.txt";
open(HANDLE, $file) or die("Cant open the file :( ");
#server_list = <HANDLE>;
close(HANDLE);
#debug_print_array(#server_list);
open(HANDLE, ">>$output_file"); #opening file for output.
foreach $host (#server_list)
{
my $ssh = Net::SSH::Perl->new($host);
$ssh->login($usr,$pwd,$ssh);
my($stdout, $stderr, $exit) = $ssh->cmd("ldd --version|grep ldd");
print HANDLE "----------------------------------";
print HANDLE "Hostname : $host";
print HANDLE "GLIBC Version : $stdout";
print HANDLE "----------------------------------\n\n";
}
You have a newline at the end of the server name.
Add:
chomp #server_list;
(And incidentally, it's better to use the newer 3-argument open(); see http://perlmaven.com/open-files-in-the-old-way .)

Perl script works with -w switch but not without

This script works on localhost with the -w switch but not without. It also works when use strict and use warning are active.
apache2/error.log:
without switch (aborted script):
(2)No such file or directory: exec of ... failed
with the switch I get:
Use of uninitialized value $email_flag in string ne ...
which looks initialised to me.
On the live web server neither one works. Perl is new to me, but I know some BASH and PHP.
I run Debian Lenny, Apache2, Perl 5.10.
#!/usr/bin/perl -w
$| = 1;
my $mailprog = '/usr/sbin/sendmail'; # where the mail program lives
my $to = "not\#for.you"; # where the mail is sent
my ($command,$email,#pairs,$buffer,$pair,$email_flag) ;
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
#pairs = split(/&/, $buffer);
foreach $pair (#pairs) {
# Split the pair up into individual variables. #
my($name, $value) = split(/=/, $pair);
# Decode the form encoding on the name and value variables. #
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
# If they try to include server side includes, erase them, so they
# aren't a security risk if the html gets returned. Another
# security hole plugged up.
$value =~ s/<!--(.|\n)*-->//g;
## print "Name of form element is $name with value of $value \n";
if ($name eq 'email') {
$email = $value;
}
if ($name eq 'command') {
$command = $value;
}
}
if ($email =~ /(#.*#)|(\.\.)|(#\.)|(\.#)|(^\.)/ ||
$email !~ /^.+\#(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/ ) {
$email_flag = "ERROR";
}
my $urlcommand = $command;
if ($command eq 'Subscribe') {
$command = "SUBSCRIBE rpc-news";
}
if ($command eq 'Unsubscribe') {
$command = "UNSUBSCRIBE rpc-news";
}
if ($command eq 'Suspend') {
$command = "SET rpc-news NOMAIL";
}
if ($command eq 'Resume') {
$command = "SET rpc-news MAIL";
}
my $getInfo = '';
print "Content-Type: text/html\n";
if ($email_flag ne "ERROR") {
open(MAIL,"|$mailprog -t");
print MAIL "To: $to\n";
print MAIL "From: $email\n";
print MAIL "Subject: [rpc-news] $command \n";
print MAIL "Reply-to: $email \n";
print MAIL "$command \n";
print MAIL "EXIT \n";
close (MAIL);
$getInfo = "?result=good";
}
if ($email_flag eq "ERROR") {
$getInfo = "?result=bad";
}
my $rootURL= $ENV{'SERVER_NAME'};
my $url = "http://${rootURL}/thank_you.html${getInfo}&action=${urlcommand}";
print "Location: $url\n\n";
Did you create your script on a Windows machine and upload it to a Linux server without fixing the line endings? Without the -w switch, the shebang line may look like "#!/usr/bin/perl\r", so the system goes looking for a program named "perl\r" (or however the line ending looks). With the -w switch, "#!/usr/bin/perl" doesn't have an indecipherable line ending stuck to it. Instead, that gets stuck to -w where it doesn't cause failure.
I thought there was a perlfaq about this, but I can't seem to find it in the docs at the moment.
Update: I found it over on PerlMonks, in a really old Q&A topic that seems unrelated until you read the body of the message: Answer: How to get rid of premature end of script headers. Yeah, I know, if you were just browsing threads you wouldn't even stop on that one. But here's the text of the post:
If you developed this script on
Windows, it's possible that the script
file has non-UNIX line endings. (The
perl interpreter can handle them, but
the shebang line is interpreted by the
shell, and is not tolerant of
incorrect line endings.) If this is
the problem, the script may terminate
with an error right at the shebang
line.
Use of uninitialized value $email_flag in string ne ...
which looks initialised to me.
if ($email =~ /(#.*#)|(\.\.)|(#\.)|(\.#)|(^\.)/ ||
$email !~ /^.+\#(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/
) {
$email_flag = "ERROR";
}
$email_flag only gets initialized here if the pattern matches - otherwise it's left undefined. You could add an else clause to ensure it gets initialized no matter what.
I would not use that code, it doesn't use CGI.pm (or CGI::Simple ...)
Get "TFMail -- Improved Form Mail" from "nms - web programs written by experts"
Its simple to install, and its written well ( it uses CGI ...)

cant connect to remote machine using WMI and Perl

I'm trying to write a script that will get event log information off of a remote windows machine using the win32::ole module and a WMI query. I can ping the machine but no matter what my WMI connection always fails using the ConnectServer() method. I'm pretty sure its not a firewall related problem. Here is my code:
use Win32::OLE qw(in);
use Net::Ping;
use constant wbemFlagReturnImmediately => 0x10;
use constant wbemFlagForwardOnly => 0x20;
my $computer = "10.10.10.15";
my $user = "Administrator";
my $pwd = "pass";
$p = Net::Ping->new();
print "$computer is alive.\n" if $p->ping($host);
$p->close();
my $locatorObj =Win32::OLE->new("WbemScripting.SWbemLocator") or die "ERROR CREATING OBJ";
$locatorObj->{Security_}->{impersonationlevel} = 3;
my $objWMIService = $locatorObj->ConnectServer($computer, "root\civm2", $user, $pwd) or die "WMI connection failed.\n";
my $colItems = $objWMIService->ExecQuery("SELECT * FROM Win32_NTLogEvent", "WQL",
wbemFlagReturnImmediately | wbemFlagForwardOnly);
foreach my $objItem (in $colItems) {
print "Category: $objItem->{Category}\n";
print "CategoryString: $objItem->{CategoryString}\n";
print "ComputerName: $objItem->{ComputerName}\n";
print "Data: " . join(",", (in $objItem->{Data})) . "\n";
print "EventCode: $objItem->{EventCode}\n";
print "EventIdentifier: $objItem->{EventIdentifier}\n";
print "EventType: $objItem->{EventType}\n";
print "InsertionStrings: " . join(",", (in $objItem->{InsertionStrings})) . "\n";
print "Logfile: $objItem->{Logfile}\n";
print "Message: $objItem->{Message}\n";
print "RecordNumber: $objItem->{RecordNumber}\n";
print "SourceName: $objItem->{SourceName}\n";
print "TimeGenerated: $objItem->{TimeGenerated}\n";
print "TimeWritten: $objItem->{TimeWritten}\n";
print "Type: $objItem->{Type}\n";
print "User: $objItem->{User}\n";
print "\n";
}
Any ideas why my attempt to connect always fails? Thanks :)
The ConnectServer call has a couple of potential issues:
I believe it needs two back slashes.
And It has a typo: civm2 -> cimv2
And it might reveal more information by adding a call to retrieve the error information:
my $objWMIService = $locatorObj->ConnectServer($computer, "root\\cimv2", $user, $pwd)
or die "WMI connection failed.\n", Win32::OLE->LastError;