Using telnet with pipe with backticks in perl - perl

I am trying to test a specific server is up and running on a certain port so I am using
$result = `echo exit | telnet 127.0.0.1 9443`; print $result;
Here I am using localhost for privacy issues
The expected behavior is that it should print "...Could not open connection to the host, on port 9443: Connect failed", this way I know that the server is not running. but it prints an empty string
Any help on this

The failure message is printed to STDERR, while backticks return only what goes to STDOUT.
You can redirect the STDERR stream to the STDOUT stream
$result = `echo exit | telnet 127.0.0.1 9443 2>&1`;
See I/O redirection.
There are more rounded ways to do this, using various forms of open. See it in perlfaq8. There are also various modules for this. The Capture::Tiny makes it rather easy.
use warnings 'all';
use strict;
use Capture::Tiny qw(capture);
my $cmd = 'echo exit | telnet 127.0.0.1 9443';
my ($stdout, $stderr) = capture {
system ( $cmd );
};
print "STDOUT: $stdout";
print "STDERR: $stderr";
This prints for me
STDOUT: Trying 127.0.0.1...
STDERR: telnet: connect to address 127.0.0.1: Connection refused
The module has many more capabilities. From the docs
Capture::Tiny provides a simple, portable way to capture almost anything sent to STDOUT or STDERR, regardless of whether it comes from Perl, from XS code or from an external program.

Related

Perl script fails to open port number on modem fails

I have a perl script to telnet to particular IP and port number. However, if i print the result after establishing connection, the port number is 23 (default). As a result, at commands triggered from script are not encouraged by modem.
Below is my script. Please advise.
Script:
#!/usr/bin/perl -w
use lib ("/u/dclement/lib/perl");
use Net::Telnet ();
$HOSTNAME = "192.168.xx.xx";
$HOSTPORT = "9998";
$conn = new Net::Telnet (Timeout => "1");
$conn->binmode(1); # don't translate CRLF
$conn->errmode("return"); # enable error trapping
$conn->telnetmode(0); # turn off telnet mode
$conn->dump_log("LOGFILE"); # output log file filehandle
$conn->output_record_separator("");
print "CONNECTING TO $HOSTNAME and $HOSTPORT\n";
# open connection to host $HOSTNAME and port $HOSTPORT
# and die if there is a problem
unless ($conn->open(Host => $HOSTNAME, Port => $HOSTPORT))
{
die "Error opening socket:: ".$conn->errmsg();
}
print "CONNECTED TO ".$conn->host().", PORT ".$conn->port()."\n";
OUTPUT
CONNECTING TO 192.168.xx.xx and 9998
CONNECTED TO 192.168.xx.xx, PORT 23
Can you try below code and see if any connectivity issue 9998 port:
$telnetOutput =telnet 192.168.xx.xx 9998;
print "\n telnet command output1: $telnetOutput \n";
$telnetOutput =telnet 192.168.xx.xx 23;
print "\n telnet command output2: $telnetOutput \n";

Connection Refused While connecting Host Through Net::FTP in perl

When I run below code through perl script at that time I always get error like connection refused so please any body can suggest to solve this issue.
ftp_check.pl:
#!/usr/bin/perl
use strict;
use warnings;
use Net::FTP;
my $host = '111.118.248.24';
#-- connect to ftp server
my $ftp = Net::FTP->new($host, Debug => 1) or die "Error connecting to $host: $!";
Message getting like "Error connecting to 111.118.248.24: Connection refused at ftp_check.pl line 10."
i supposed you server works properly, just for the case you can make some pings on it. Anyway, do you have a possibility to run in a terminal ( with ssh or some client like putty if you are a windows user ) following commands:
netstat -tulpena | grep -i LIST <<ENTER>>
Now you can see is there a FTP-Server which is running in a listener mode.
The second step would be to to use some ftp-client to check, that you can connect with your FTP-Server properly, just to see is there a firewall-rule in between, actually you could run "iptables -L" on a server to, but it will be easier just to use some ftp-client to make a verification of your ftp-server.
An other suggestion would be to use something more secure
and not the net::ftp-module. Perl has nice CPAN-Modules for SFTP (Net::FTP).
Cheers.

Perl read line string without trailing newline

Very new to perl and have been stuck for quite awhile on this.
If I change the variable from READSTDIN to google.com, it says google.com is online as it should. If I use the STDIN and input google.com and print $host it prints google.com, however in the ping it doesn't work.
Sample output:
perl perl.pl
What is the website that is offline or displaying an error?google.com
Warning: google.com
appears to be down or icmp packets are blocked by their server
Code:
use strict;
use warnings;
use Net::Ping;
#optionally specify a timeout in seconds (Defaults to 5 if not set)
my $timeout = 10;
# Create a new ping object
my $p = Net::Ping->new("icmp");
#Domain variable
print "What is the website that is offline or displaying an error?";
my $host = readline STDIN;
# perform the ping
if ( $p->ping( $host, $timeout ) ) {
print "Host $host is alive\n";
} else {
print "Warning: $host appears to be down or icmp packets are blocked by their server\n";
}
# close our ping handle
$p->close();
If I change the variable from READSTDIN to google.com, it says google.com is online as it should. If I use the STDIN and input google.com and print $host it prints google.com, however in the ping it doesn't work. I appreciate anyone who can help me at all!
Note the newline in your input:
perl perl.pl
What is the website that is offline or displaying an error?google.com
Warning: google.com <--- newline after google.com puts the rest of the output on the next line...
appears to be down or icmp packets are blocked by their server
You should be using chomp to remove the newline from your input:
chomp( my $host = readline STDIN );
Or more simply:
chomp( my $host = <STDIN> ); # same thing as above

Display Output In Browser Perl CGI SSH

I'm executing remote commands using Net::OpenSSH using a web frontend. My commands return without failure on the command line, but I get nothing in a web browser. I've done a couple hour research to no avail--any ideas?
Here is some code to give you an example (some removed for obvious reasons).
#!/usr/bin/perl -w
use strict;
use CGI ':standard';
use Net::OpenSSH;
# Here in the code is just the header and standard tags
print "1";
print "2"; # both display
my $ssh = Net::OpenSSH->new($host, user => $uname, key_path => $key); # all works
$ssh- error and die "Can't ssh to host" . $ssh->error;
print "3";
$ssh->system("uname -a") or
die "remote command failed: " . $ssh->error;
my #lsa = $ssh->capture("ls -a");
$ssh->error and
die "remote ls command failed: ". $ssh->error;
print "4";
print "5";
print #lsa; # won't display in browser, just terminal/CLI
Cheers!
I maintain CGI.pm. I recommend these additions to your simple script:
Before you print anything else, print the standard HTTP header: print header();
Add this after the use CGI line: use CGI::Carp qw(fatalsToBrowser); ... that will display any run-time problems in the browser. If you don't get any output after these changes, check that the script compiles with perl -cw script.pl
Below is about the minimum Perl code that worked for me on Debian machine. I suggest you go through it and compare it to your actual code.
However, it did not work out-of-the box on my Debian, I had make some decisions most of which probably aren't very safe, but that's more about specific environment:
make home for user that server runs writable (/var/www)
add host to ~/.ssh/known_hosts beforehand
use the strict_mode => 0 to bypass Net::OpenSSH's security checks instead of finding proper
ctl_dir (Net::OpenSSH requires that the folder and all above folders are 0755 or more strict,
so /tmp I used is normally not good enough)
I believe there are much safer practices than that, but as I said, that's specific to environment.
So the code:
#!/usr/bin/perl
use strict;
use warnings;
use Net::OpenSSH;
use File::Temp qw/ tempdir /;
# necessary minimum for CGI
print "Content-type: text/plain\n\n";
# prepare temp dir
my $temp = tempdir("/tmp/sshme.pl-XXXXXXXX", CLEANUP => 1);
# open SSH session
my %opts = (
user => "user",
password => "password",
ctl_dir => $temp,
strict_mode => 0 ## NOT recommended - see my comments
);
my $ssh = Net::OpenSSH->new("host", %opts);
$ssh->error
and die "Couldn't establish SSH connection: ". $ssh->error;
# perform command and print output
my #lines = $ssh->capture("ls")
or die "remote command failed: " . $ssh->error;
print #lines;
Perhaps your errors get directed to standard error, not standard output. In that case, they'll usually end up in the server log, not the browser window. Perhaps you can use POSIX::dup2 to avoid this:
use POSIX;
# Make sure to send HTTP headers before redirecting streams!
POSIX::close(2); # close original stderr stream. No more output to apache logs!!!
POSIX::dup2(1,2); # redirect error stream to standard output, so errors will appear in browser.
Processes launched by perl, like e.g. some ssh binary, will inherit these streams.

How can I get STDERR and STDOUT of a command executed on a remote machine through SSH in Perl?

I have to connect to a remote machine via SSH executed through Expect module. I have to access the STDERR/STDOUT separately if possible and look at the output. I can redirect the output of the script e.g.
$command = "ssh <script> 2>/tmp/stderr.output"
$exp = Expect->spawn($command) or die "Cannot spawn\n";;
my #command1= $exp->expect(5);
but then I have to remotely connect again to check stderr.output.
Is there a way that expect returns the STDERR/STDOUT separately.
You might want to consider using Net::OpenSSH which provides a capture2 method:
($output, $errput) = $ssh->capture2(\%opts, #cmd)
captures the output sent to both stdout and stderr by #cmd on the remote machine.