How to set the shell of remote server through perl telnet - perl

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;

Related

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

Perl Net::SSH doesn't receive prompts

I am writing a script to communicate with a remote server. I understand how to send a basic shell command such as "ls" or "find / |grep foo". But I am executing an interactive application at the other end.
If I call $ssh->shell, I get the prompt from the remote server so I know that SSH is receiving this prompt. But then I can't do anything because the script is blocked in a shell.
I installed two handlers. If I use the script to connect to a basic ssh host, and execute a shell command, the response is delivered to the handlers, so I know they are ok. So I expected the prompt from the application I am executing to be sent to these but it isn't.
#!/usr/bin/perl -w
use strict;
use Net::SSH::Perl;
my $host = 'rt.olsendata.com';
my $user = 'rtdemo';
my $pass = 'rtdemo';
my %params = ('debug' => 1,'protocol' => 2);
my $ssh = Net::SSH::Perl->new($host, %params);
$ssh->register_handler("stderr", sub{
my ($ssh, $packet) = #_;
receiveerrors($packet);
});
$ssh->register_handler("stdout", sub{
my ($ssh, $packet) = #_;
receivedata($packet);
});
my ($output, $errors, $exit) = $ssh->login($user, $pass);
At this point I need to respond to the prompt by sending a "1". But this is interpreted by the remote host as a shell command, not a response to the prompt. It returns the error "h: 1: No such file or directory".
If you want to try it you can use the demo ssh account at the top of the code. It is publicly available.
Edit: I realise that Expect solves this issue, but I could not find any equivalent to register_handler() in Expect. Am I right in this?
I use expect to automate ssh/sftp sessions.
Net::SSH::Perl provides shell() method for "interactive" sessions. Otherwise, this one, like its brethren, assumes that you're executing a single command on a remote server.
The simplest solution by far is Net::SSH::Expect. Below is the code. Immediately upon login I need to send a "1" in response to the prompt ("1" is the choice I want). Then I get another prompt and since I want the default value I just send \n. Then I want to read the input line by line forever. It works like a charm.
my $ssh = Net::SSH::Expect->new (
host => $host,
user => $user,
password=> $pass,
raw_pty => 1
);
my $login_output = $ssh->login();
my $prompt = $ssh->exec("1");
my $line;
$ssh->send("\n");
while ( defined ($line = $ssh->read_line()) ) {
print "$line\n";
}

How to run SSH commands using Net::SSH::Perl?

I don't know if I managed to install Net::SSH::Perl module successfully but I can't seem to be able to run the following code:
my $ssh = Net::SSH::Perl->new($remote_host);
$ssh->login($username, $password);
print "login done", "\n";
my ($out, $err, $exit) = $ssh->cmd($cmd);
print "$out", "\n";
I am able to login but cannot print the $out. I keep getting this error:
Use of uninitialized value $out in string at test_ssh.pl line 28.
Line 28 refers to print "$out", "\n";.
I am running this code on Cygwin. What should I do now?
EDIT:
I got the following error msg when I ran my $ssh = Net::SSH::Perl->new($remote_host, options => ["Debug yes"]);:
Use of uninitialized value $out in string at test_ssh.pl line 29 (#1)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.
To help you figure out what was undefined, perl will try to tell you the
name of the variable (if any) that was undefined. In some cases it cannot
do this, so it also tells you what operation you used the undefined value
in. Note, however, that perl optimizes your program and the operation
displayed in the warning may not necessarily appear literally in your
program. For example, "that $foo" is usually optimized into "that "
. $foo, and the warning will refer to the concatenation (.) operator,
even though there is no . in your program.
EDIT2:
Here's my full code
use strict;
use warnings;
use Net::SSH::Perl;
my $remote_host = '<host ip address>';
my $password = 'pass';
my $username = 'user';
my $cmd = 'copy run tftp:<my own ip address>';
warn "Starting SSH Services:...";
my $ssh = Net::SSH::Perl->new($remote_host, debug => 1);
print "done", "\n";
warn "Starting Login:...";
$ssh->login($username, $password);
print "login done", "\n";
warn "Starting command:...";
#$ssh->cmd($cmd);
#my($stdout, $stderr, $exit) = $ssh->cmd($cmd);
my ($out, $err, $exit) = $ssh->cmd($cmd);
print "$out", "\n";
The error message on "print "$out","\n";" line:
<Computername>: channel 1: new [client-session]
<Computername>: Requesting channel_open for channel 1.
<Computername>: Entering interactive session.
<Computername>: Channel open failure: 1: reason 4:
Use of uninitialized value $out in string at test_ssh.pl line 29.
LAST EDIT: I decided to use Net::Appliance::Session to login via SSH to the network devices instead. it's a lot easier to use than Net::SSH::Perl.
Please show more of your code. What is the value of $cmd?
Note that the login method doesn't perform a login: it merely stores the username and password to be used when the connection is set up for each cmd call.
The correct way of enabling debugging messages is
my $ssh = Net::SSH::Perl->new($remote_host, debug => 1);
This will give you trace information from the cmd method which should say, amongst other things
Sending command: xxx
Entering interactive session.
and should give you some clues about what is going wrong.
Your debug output shows the problem. Looking at SSH2.h, open failure reason 4 is SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED. Your username and password are incorrect.
Net::SSH::Perl does support login via username/password, I have a working example, I just got this to work. I used the code from above and took out the Double Quotes (" ") and used single quotes (' ') instead. And "debug => 1" works for debugging the code when having issues. It will display info to you when you try to login if the debug option is set.
I am connecting to a Win32-OpenSSH SSHD server based on Windows Powershell very similar to BSDLinux SSHD server with SFTP support. Supports same Linux style based connection.
I have been trying all other SSH modules all day. Hopefully someone can use this code to just run a command and get the output if required.
You can install Net::SSH::Perl with "cpan -i module-name"
use Net::SSH::Perl;
my $host = 'testmachine.acme.local'; #Or just IP Address
my $user = 'domain\username'; #Or just username
my $pass = 'Password#123';
my $cmd = 'dir C:\\Windows\\';
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new($host, debug => 1);
$ssh->login($user, $pass);
my ($out, $err, $exit) = $ssh->cmd($cmd);
print "$out", "\n";
Net::SSH::Perl does not support login via username/password only via interactive password entry or public key. See this post for more information.
http://www.perlmonks.org/?node_id=590452

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

How can I use Expect to enter a password for a Perl script?

I wish to automatically enter a password while running an install script. I have invoked the install script using the backticks in Perl. Now my issue is how do I enter that password using expect or something else?
my $op = `install.sh -f my_conf -p my_ip -s my_server`;
When the above is executed, a password line is printed:
Enter password for the packagekey:
In the above line I wish to enter the password.
use Expect.pm.
This module is especially tailored for programatic control of applications which require user feedback
#!/usr/bin/perl
use strict;
use warnings;
use Expect;
my $expect = Expect->new;
my $command = 'install.sh';
my #parameters = qw(-f my_conf -p my_ip -s my_server);
my $timeout = 200;
my $password = "W31C0m3";
$expect->raw_pty(1);
$expect->spawn($command, #parameters)
or die "Cannot spawn $command: $!\n";
$expect->expect($timeout,
[ qr/Enter password for the packagekey:/i, #/
sub {
my $self = shift;
$self->send("$password\n");
exp_continue;
}
]);
If the program reads the password from standard input, you can just pipe it in:
`echo password | myscript.sh (...)`
If not, Expect or PTYs.
You can save the password in a file and while running the install script, read the password from the file.