Perl - Best way to establish an SFTP connection on windows - perl

I need to put files in a remote directory using SFTP on a Windows machine. I've tried Net::SFTP::Foreign though I can't use it because it needs IO::Pty which is not available on Windows machine. What's the best/simplest way to do this?
Update With Requested Info:
Here are the versions I'm using:
Net::SFTP::Foreign : v 1.89
Net::SSH2 : v 0.69
Net::SFTP::Foreign::Backend::Net_SSH2 : v 0.09
and here is the gist of my code:
$ssh2 = Net::SSH2->new();
$ssh2->connect($host) || die "connect failed";
$ssh2->auth_password($user, $pass) || die "password auth failed";
$sftp = Net::SFTP::Foreign->new(ssh2 => $ssh2,
backend => 'Net_SSH2');
$sftp->error and
die "Unable to stablish SFTP connection: ". $sftp->error;
Right now I'm just trying to establish a connection. I will need to put files on the server. The erro I'm receiving is as follows:
Net::SSH2::timeout(ss, timeout) at C:/Strawberry/perl/site/lib/Net/SSH2.pm line 111, <STDIN> line 1.

The preferred way to use Net::SFTP::Foreign in Windows is probably to use the Net::SFTP::Foreign::Backend::Net_SSH2 backend (update: a Perl module available from CPAN) which uses Net::SSH2 under the hood (which is already included with Strawberry Perl, update: otherwise, you will need to build and install libssh2 yourself which sometimes is not as easy as it should be).
Another option is to tell Net::SFTP::Foreign to use the plink command to run the SSH connection (search for plink on the module docs). Update:plink is part of the PuTTY application distribution, a very popular SSH client that may be already installed in that machine.
Finally you can also try using Net::SSH::Any which provides its own backend for Net::SFTP::Foreign and can run on top of several SSH clients and modules... but it is still in beta!

I have several cross-platform scripts that are using Net::SFTP::Foreign using plink on windows and openssh on linux and it works great. Windows is using the latest strawberry perl release.
my $sftp = Net::SFTP::Foreign->new(
host=> $server,
ssh_cmd => $plink, #Contains full path to plink or path to ssh
user=> $user,
more => ['-i', $keyfile],
stderr_discard => 1,
);
The only thing about using the plink backend is that you have to first manually establish a connection using psftp or Putty gui so it stores the trust confirmation in the registry. After that it is good to go from the script.
The nice thing is you can just have the actual path to ssh or to plink defined in a system level config file and the script just reads what is needed on that particular platform. ie (...\bin\Putty\plink.exe or /usr/bin/ssh )
Not a pure Perl solution, but has been very robust. I don't see IO::Pty on any of my windows boxes so no dependency there for plink.

SFTP is actually SSH with a wrapper to simulate the FTP like commands, so a mdir is actually a ssh 'ls /path/to/dir'.
While there might be a Perl SFTP package that avoids IO::Pty, you might get to your solution much faster by just translating the "FTP" commands into their ssh / scp equivalents and looking at Net::SSH
--- Adding an Example as requested ---
#!/bin/env perl
use Net::OpenSSH ();
my $connection = Net::OpenSSH->new('somehost.com', user => 'myuser', password => 'mypassword' );
my #ls = $connection->capture("ls");
printf "remote listing is %s\n", join(', ', #ls);
This should list the files to your console.
You mentioned not having IO::Pty because it is not available for a windows machine. Perhaps you should be attempting to install IO::Pty::Easy. Note that Net::OpenSSH uses IO::Pty too, but that should be possible to do on windows, provided you also install Glib as indicated in this post http://www.perlmonks.org/bare/?node_id=856863
Good luck!

Related

[Perl][net::ssh2] How to keep the ssh connection while executing remote command

I'm working on a perl script using net::ssh2 to make a SSH connection to a remote server.
(I'm working on windows)
I chose Net::SSH2 because i had to make some SFTP connections in the same script.
For now, my sftp connections work perfectly. The problem is when i try to execute a "long-duration" command. I mean a command which execution can take more than 30sec.
$ssh2 = Net::SSH2->new();
$ssh2->connect('HOST') or die;
if($ssh2->auth(username=>'USER', password=>'PSWD'))
{
$sftp = Net::SFTP::Foreign->new(ssh2=>$ssh2, backend=>'Net_SSH2');
$sftp->put('local_path', 'remote_path');
$channel=$ssh2->channel();
##
$channel->shell('BCP_COMMAND_OR_OTHER_PERL_SCRIPT');
# OR (I tried both, both failed :( )
$channel->exec('BCP_COMMAND_OR_OTHER_PERL_SCRIPT');
##
$channel->wait_closed();
$channel->close();
print "End of command";
$sftp_disconnect();
}
$ssh2->disconnect();
When i execute this script, the connection is successfull, the file is correctly sent but the execution is not (completely) performed. I mean, I think the command is sent for execution but terminated immediatly or not sent at all, i'm not sure.
What i want is the script waits until the command is completly finished before disconnect everything (just because sometimes, i need to get the result of the command execution)
Does anyone know how to solve this? :( The cpan documentation is not very explicit for this
Thanks!
PS: I'm open to any remarks or suggestion :)
Edit: After some test, i can say that the command is sent but is interrupted. My test was to start another perl script on the remote server. This script writes in a flat file. In this test, the script is started, the file is half-filled. I mean, the file is brutaly stopped in the middle.
In the other hand, when i performed a "sleep(10)" just after the "$channel->exec()", the script goes to the end successfully.
Problem is, that I can't write a "sleep(10)" (i don't know if it will take 9 or 11 seconds (or more, you see my point)
You can try using Net::SSH::Any instead.
It provides a higher level and easier to use API and can use Net::SSH2 or Net::OpenSSH to handle the SSH connection.
For instance:
use Net::SSH::Any;
my $ssh = Net::SSH::Any->new($host, user => $user, password => $password);
$ssh->error and die $ssh->error;
my $sftp = $ssh->sftp;
$sftp->put('local_path', 'remote_path');
my $output = $ssh->capture($cmd);
print "command $cmd output:\n$output\n\n";
$sftp->put('local_path1', 'remote_path1');
# no need to explicitly disconnect, connections will be closed when
# both $sftp and $ssh go out of scope.
Note that SFTP support (via Net::SFTP::Foreign) has been added on version 0.03 that I have just uploaded to CPAN.

PERL SFTP using System, Cannot install SFTP module

I'm a bit new to perl and stackoverflow. If I could use a more familiar language I would, unfortunately I cannot due to certain circumstances. Thanks in advance for the help.
Modules Not Installed: Net::SFTP, WWW::CURL, Net::SSH2, Net::SFTP::Foriegn
Modules Installed: Net::FTP
I am unable to install modules.
Unable to use Net::FTP Tried Default port and port 22, with a username and password. All I get back from the other box's log when trying to connect is "Did not receive identification string from xx.xx.xx.xx" Also unable to use FTP in command line, times out.
$ftp = Net::FTP->new($box,Port=>22, Debug => 0)
or die print "Error: Cannot connect";
$ftp->login($userBox,$passBox)
or die print "Error: Cannot login";
$ftp->cwd()
or die print "Error: Cannot change to Root";
$ftp->cwd($dir)
or die print "Error: Cannot change to selected directory";
if($copyfile ne "" && $dir ne "")
{
$ftp->put($copyfile, $copyfile);
}
$ftp->quit();
I can manually use SFTP through the linux command line, not FTP, so I have been trying to use the system command to SFTP into the other box. The other box's logs just say "Connection closed by xx.xx.xx.xx"
system('sftp '.$userBox.'#'.$box.' ENDOFINPUT'
.$passBox.'ENDOFINPUT
cd ../../../
put '.$filename.' '.$dir.'
exit
ENDOFINPUT');
If anyone knows how to help me with my problem that'd be great :)
Let's approach this from another direction... when you say you're "unable to install modules", is that just because you don't have root permission? If that's the case, you can install them locally under a user account instead.
If the machine doesn't have an internet connection to even install them locally, you can use the same technique to install them on a different box, then gzip the entire local directory where you have them installed and copy them to the target machine, and add a "use lib" statement to get at them from your script.
Are you sure that the $passBox equivalent worked on the shell?
You should be able to set-up passwordless connectivity using key-pairs, which would make THAT problem go away quite quickly.

Perl script cant find Net/SSH/Perl.pm

Im trying to run a perl script which involves ssh to a remote server and while executing this code, it throws an error like
Can't locate Net/SSH/Perl.pm in INC <#INC contains:C:/Perl/site/lib c:\perl\lib at line5.
I open ppm graphical UI and installed NET-SSH, area= site
but still not able to execute this script
Here is the script
use strict;
use warnings;
use Net::SSH::Perl;
my $ip=12.14.142.22;
my $user = "qwerty";
my $pass = "termide";
my $ssh = Net::SSH::Perl->new($ip, use_pty => 1);
$ssh->login($user, $pass);
While Foo::Bar often includes a Foo::Bar::Baz module, that isn't the case here.
Net::SSH and Net::SSH::Perl are different distributions. You need to install Net::SSH::Perl.
You should install Net::SSH::Perl, not Net::SSH. The error message is clean about that :)
Net::SSH2 is another SSH client that works on Windows and far easier to install. A PPM is available from here.

How to do remote execution in standard perl 5.10.0

I want to run some commands via a remote program. I've tried it using following code.
my $promt = '/bash\$ $/';
use Net::Telnet ();
$conn = new Net::Telnet (Timeout => 10, Prompt => $promt);
$conn->open($host);
$conn->login($username, $passwd);
#lines = $conn->cmd("who");
print #lines;
But it gives error,
Can't locate Net/Telnet.pm in #INC.....
Is there way to do this task without changing, adding standard perl 5.10.0 modules?
Just install the Net::Telnet perl module in your own user path. OR if you are not bound to perl, the best way i can suggest to run commands on remote systems is SSH.
$ssh user#ip 'command'
This will give you the results in STDOUT.
Examples:
root#www:~ # ssh root#www 'who'
brock pts/0 Oct 21 10:31 (75.72.194.149)
jim pts/1 Oct 25 06:25 (128.101.163.128)
You can find few more at "Run Remote Command with SSH".
Ive solved the problem using this function...
# Get the needed values from the database
sub Execute_Remote_Command($) {
print "sshpass -p $password ssh $user\#$host '$_[0]'\n";
print `sshpass -p $password ssh $user\#$host '$_[0]'`;
print `exit`;
}
Function -Execute_Remote_Command- needed a parameter which needed to be run in the remote machine.
The only additional requirement needed here is supporting sshpass command and it can be downloaded using following url.
http://linux.softpedia.com/get/Security/Sshpass-8693.shtml

problem making an SSH session using perl

use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new('$host',22);
$ssh->login('$user','$pass');
my $out = $ssh->cmd("show clock");
print $out;
I have the above script to have an ssh session using perl but I'm having the error message
"Can't map service name 'ssh' to port number". I'm using Windows OS. Please advise me where I'm wrong.
Try adding ssh to your services file. The services file is located at:
%SystemRoot%\system32\drivers\etc\services
The line that you'll want to add will look like:
ssh 22/tcp # Secure Shell Login