Is there a way to allow perl to initiate a telnet session and programmatically issue commands to that telnet session?
I initially tried a stupid method:
commands.pl:
sleep(1);
print $command1;
sleep(1);
print $command2;
and then
> perl commands.pl | telnet www.host.com port
This does not work.
There is a Net::Telnet module.
use Net::Telnet ();
$t = new Net::Telnet (Timeout => 10,
Prompt => '/bash\$ $/');
$t->open("sparky");
$t->login($username, $passwd);
#lines = $t->cmd("who");
print #lines;
(Example taken from that page.)
One option would be through Perl's interface to Expect.
Related
I'm trying to create a script in Perl that does the following
On a Windows 2008 R2 server, connects to a local OpenWRT router.
Send some commands to the router and save the output (interface brief)on a varaible
Edit the content of the variable (to keep the IP only)
Send the variable again to the router withinin another command
I created a socket but i dont seem to get any luck sending commands to the router. I'm not even sure if I'm logging in.
Here is my code:
use IO::Socket;
use strinct;
use warnings;
$iaddr = gethostbyname("192.168.1.237");
$ssh_port = 22;
$sin = sockaddr_in($ssh_port, $iaddr);
socket(DEV, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
connect(DEV, $sin) || die "Can't connect to EN4000: $!\n";
print DEV "user\n";
print DEV "password\n";
print DEV "echo test >> /etc/config/networkTest \n";
I run it, check the file /etc/config/networkTest but no modification is made
Have a look at Net::SSH::W32Perl
Here's a quick example;
#!/usr/bin/env perl
use strict;
use warnings;
use Net::SSH::W32Perl;
my $host='example.com';
my $user='john';
my $pass="pass";
# Connect
my $ssh = Net::SSH::W32Perl->new($host);
$ssh->login($user, $pass);
# Run command
my $cmd = q(echo test >> /etc/config/networkTest);
my($stdout, $stderr, $exit) = $ssh->cmd($cmd);
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 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;
Have a perl script to connect with a Java service running on localhost, passes encrypted cookie, and returns decrypted data. When I run script from command line, it works fine. Even gave apache user a shell, and ran from command line as that user, which also works fine. If the script is run as CGI from apache, the socket new returns undef and $! is set with "permission denied". ???
Running CentOS 6.3 on this server, and IPtables are disabled.
#!/usr/bin/perl
use strict;
use CGI;
use IO::Socket;
use JSON;
my $cgi = CGI->new();
my $cookie = $cgi->cookie('attESSec') || shift (#ARGV) || undef;
my $data = JSON::false;
if($cookie){
my $socket = IO::Socket::INET->new(
'PeerHost' => '127.0.0.1',
'PeerPort' => '1500',
'Proto' => 'tcp'
);
if($socket){
$socket->send($cookie . "\r\n");
$socket->recv(my $auth,1024);
$socket->close();
chomp($auth);
if($auth){
$data = (split(/\|/,$auth))[5];
}
}
else{
$data = $!;
}
}
print($cgi->header('application/javascript'));
print(JSON->new()->allow_nonref()->utf8()->encode($data));
exit();
I found the answer. The problem was SElinux. By default it doesn't let the httpd process (or anything that spawns from it, such as CGI scripts) establish network sockets. So just had to enable that particular feature with command "setsebool -P httpd_can_network_connect 1". Now it works perfectly.
I am trying to automate telnet to a Linux box which doesn't require any authentication through Net::Telnet Perl module. Here is a test script:
use strict;
use Net::Telnet;
my $telnet = new Net::Telnet ( Timeout=>10, Errmode=>'die',
host=> '10.104.20.200', port => 2004,
);
$telnet->print('ls');
my $output = $telnet->waitfor('/\$ $/i');
print $output;
When I execute this script, I get the below error,
pattern match timed-out at telnetPerl.pl line 7.
As you could see, I am matching for any characters in waitfor. But I doubt whether the telnet connectivity happened in the first place.
The Net::Telnet docs say under the entry for waitfor():
Use dump_log() to debug when this method keeps timing-out and you don't think it should.
What happened when you followed the doc's instructions? :)