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
Related
I have a situation where in I am calling the below Perl script
if (param("lremail") && param("lot")) {
my $address=param("lremailaddress");
my $lot=param("lot");
print a({-href=>"$dir/new.pl"},"Back to Top"),br;
print "Request submitted for $address.",br;
print "Lot $lot",br;
print "You will receive an e-mail with a link to the data when the request is complete.";
print end_html;
system ("ssh SERVERNAME /test/abc.csh $lot $$ $address &");
exit(1);
The above script does not run because when I execute the system is prompted for a password. Then I looked it up and found the below command..
expect -c 'spawn ssh SERVERNAME /test/abc.csh J213520 06 abc#gmail.com "ls -lh file"; expect "Password:"; send "PASSWORD\r"; interact'
The above command is executed successfully without any issue but from the command line only. When I incorporate the same(by replacing the system call) within the Perl script, it fails. How can I incorporate within the first script?
Reiterating and adding to comments:
Consider using a key-based authentication either with passphrase-less keys or with ssh-agent (e.g., using ssh-keygen generated/managed identities);
Consider using sshpass or another expect-like external;
Consider using the Perl Expect or an equivalent CPAN module; and/or,
Consider using the Perl Net::SSH or an equivalent CPAN module.
Also, system can easily introduce remote code execution vulnerabilities, especially when using its system LIST syntax.
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!
I am trying to run a couple of commands in putty from perl. Right now my code gets me into putty but I am unsure of how to execute commands from there.
my $PUTTY = 'C:\Users\Desktop\putty.exe';
my $dacPutty = "$PUTTY, -ssh username#server - l username -pw password";
system ($dacPutty);
system (ls);
use plink instead. ( http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter7.html )
plink is in the same directory as putty.
Usually in Perl it's better to use a Perl module, where one exists, than to shell out.
Using a module is more portable, and often gives you more control. system introduces many opportunities for security bugs, so it's good to avoid it where possible.
In this case, use Net::SSH::Perl http://search.cpan.org/~turnstep/Net-SSH-Perl-1.38/lib/Net/SSH/Perl.pm
Once installed:
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new("host1");
$ssh->login("user1", "pass1");
$ssh->cmd("cd /some/dir");
$ssh->cmd("foo");
For reliability, you should actually check the result of each cmd:
my ($stdout, $stderr, $exit) = $ssh->cmd("cd /some/dir");
unless ($exit == 0) {
// Handle failed cd
}
The document notes that with SSH-1, each cmd reconnects, so the above would not work -- you would cd in one shell, then foo in a completely new shell. If you have to use SSH-1, then you'd need to do:
$ssh->cmd("cd /some/dir; foo");
(And you can use a similar trick even if you're making a system call to plink)
I am bit stuck here I want to ssh in to a machine and then run about 3 commands which are basically setup commands and then i want to return back to my machine with env variables of that machine
like
setup1
setup2
setup3
env > envtext.txt.
return back
All this i have to do in perl
i tried commands like
system("ssh #machine command1 && command 2") doesnt work
is there something like?
system("ssh #machine command1 -cmd command 2 -cmd command 3")
if not than what is the best way to do it
like making a shell script then calling it or i can do it in perl itself without any shell scripts?
code
#!/usr/bin/perl -w
use Net::SSH::Perl;
my $host = "address";
my $user = "name";
my $password = "password";
-- set up a new connection
my $ssh = Net::SSH::Perl->new($host,
debug=>0,
identity_files => ['path to key'],
options=> ["StrictHostKeyChecking no"]
#interactive => yes,
);
-- authenticate
$ssh->login($user,$password);
-- execute the command
my($stdout, $stderr, $exit) = $ssh->cmd("env");
print $stdout;`
error it gives is Permission denied at ssh.pl line 25
Thank you
I think your question is about SSHing to a single remote host and running multiple commands there. If that's true, then you need to pack your multiple commands up into a single command line that the remote shell can execute. The easiest way to do this is to use the list form of system, and pass the command line as a single parameter:
system "ssh", "machine", "setup1; setup2; setup3";
On to the second part of your question: You want to get data back from the remote side. For that, you'll want your program to read SSH's output rather than using system. For this, you can use:
open my $FH, "-|", "ssh", "machine", "setup1; setup2; setup3; env";
my #lines_from_ssh = <$FH>;
close $FH;
If you also need to send input to the remote side, look into IPC::Open2. If you need to capture both stdout and stderr, see IPC::Open3.
What you can do :
system("ssh $_ command1 -cmd command 2 -cmd command 3") for #machines;
Another Pure Perl solution is to use Net::OpenSSH
How can I set the remote server shell to bash through the perl telnet?
My code is below:
$telnet = Net::Telnet->new(Timeout=>90,Errmode=>'die');
$telnet->open($ipAddress);
$telnet->login($username,$password);
$telnet->waitfor('/$/');
$telnet->print("exec bash");
print "after bash";
print $telnet->cmd("ls -lrt");
print $telnet->cmd("cd $homePath");
In the above code, after the exec bash statement, none of the commands are getting executed. I need to set the remote shell as bash because some of the processes I need to run after this lines require env settings.
Please let me know how can I do the same.
Your regex to wait for the command prompt is wrong
$telnet->waitfor('/$/');
Try
$telnet->waitfor('/\$ $/');
Even better, see the first example in the Net::Telnet 3.04 doc:
my $host = 'your_destination_host_here';
my $user = 'your_username_here';
my $passwd = 'your_password_here';
my ($t, #output);
## Create a Net::Telnet object.
use Net::Telnet ();
$t = new Net::Telnet (Timeout => 10);
## Connect and login.
$t->open($host);
$t->waitfor('/login: ?$/i');
$t->print($user);
$t->waitfor('/password: ?$/i');
$t->print($passwd);
## Switch to a known shell, using a known prompt.
$t->prompt('/<xPROMPTx> $/');
$t->errmode("return");
$t->cmd("exec /usr/bin/env 'PS1=<xPROMPTx> ' /bin/sh -i")
or die "login failed to remote host $host";
$t->errmode("die");
## Now you can do cmd() to your heart's content.
#output = $t->cmd("uname -a");
print #output;