Executing multiple commands using Net::SSH::Perl module - perl

I am new to this module. I tried a sample program and it worked fine. But, now I would like to how do I execute multiple commands in this program :
use Net::SSH::Perl;
my $hostname = "<<hostname>>";
my $username = "<<username>>";
my $password = "<<password>>";
my $cmd = 'mkdir script; cd script';
my $ssh = Net::SSH::Perl->new("$hostname", debug=>0);
$ssh->login("$username","$password");
my ($stdout,$stderr,$exit) = $ssh->cmd("$cmd");
print $stdout;

You can just call cmd repeatly.
The problem you are facing may be that every command is run in a different shell and commands that are run for their side effects as cd or export become useless.
As a work around you can prefix all the commands with the cd $dir command. For instance:
my ($stdout1, $stderr1, $exit1) = $ssh->cmd("cd /$dir && $cmd1");
my ($stdout2, $stderr2, $exit2) = $ssh->cmd("cd /$dir && $cmd2");
...
Another option is to run a shell on the remote host and talk to it, but this is more difficult and error prone.
Finally, Net::SSH::Perl is old and unmaintained, nowadays, Net::SSH2 or Net::OpenSSH are usually better options.

Related

Putty command from Perl

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)

Regarding running multiple ssh commands using perl

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 to set the shell of remote server through perl telnet

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;

Insert rsh and module load in perl script

I am writing a perl script to start vnc session.
Firsr I need to rsh to a server then load a module, next execute the "vncserver -otp".
my $mod=`module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log`;
my $launch=`rsh $host /"$mod/"`;
print $launch;
But it does not work, any suggestions??
Thanks!!
Did you mean to use backticks in your first line?
my $mod=`module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log`;
This sets $mod to be the output of this sequence of commands, like running
(module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log) | rsh $host
from the shell. You probably wanted to say
my $mod='module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log';
which will set you up to run those specific commands on the remote host, and execute
rsh $host "module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log"
It also looks like in the rsh command that you are trying to escape the quotation marks with forward slashes. In Perl (and in everything else as far as I know), use a backslash to escape a special character.
my $launch=`rsh $host /"$mod/"`; # / wrong /
my $launch=`rsh $host \"$mod\"`; # \ right \
my $launch=`rsh $host "$mod"`; # right, esc is not reqd in this case
A number of things could be going wrong, but probably the system commands are quietly failing. Either loading the module, starting the vncserver or the rsh. You can manually check for their success or failure by checking $? after each command... or you can use IPC::System::Simple and it will error out if the command fails.
I would start by doing it as a series of shell commands to make sure it works.
Then I'd rewrite the code like so using IPC::System::Simple to do the error checking. Also separating the $mod command into two commands, because I suspect you're getting back the output of running the vncserver, not loading the module.
use strict;
use warnings;
use IPC::System::Simple qw(run capture);
my $host = "something.something";
# Capture the output of loading the module
my $mod = capture('module', 'load', 'turbovnc-1.0.0');
warn "Module output: $mod\n";
# Run the VNC server
run('vncserver -otp 2> tmp_vnc.log');
# Connect to the host
my $launch = capture('ssh', $host, "/$mod/");
warn "ssh output: $launch";
There would seem to be a possibly false assumption that the location of the module on this machine is the same as the location of the module on the remote machine. That or I don't understand what you're doing with $mod.

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