Capturing output from Net::Telnet cmd


N

niall.macpherson

I'm using Net::Telnet for the first time.

I would like to run a command on a remote windows machine and have been
experimenting with the Net::Telnet module.

The attached test code seems to work - It just executes 'dir' on the
remote machine and redirects the output to the file.

However I want to be able to capture the output from the remote command
I am running directly rather than have to write it to an intermediate
file.

I thought I could replace this

my $cmdstring = q(dir > C:/testtelnet/diroutput.txt); ## How do I
capture output here ??
my $output = $tel_conn->cmd (String => $cmdstring);

with
my $cmdstring = q(dir);
my @output = $tel_conn->cmd (String => $cmdstring);

but I just get an array containing an empty string.

Can someone point out where I am going wrong ? TIA
------------------------------------------------------------------------------------------------------------------------------------
use strict;
use warnings;
use Net::Telnet;
use Data::Dumper;

if($#ARGV != 1)
{
print STDERR "\nUsage $0 <username> <password>";
exit(-1);
}

my $timeout = 10;

my $prompt = '/C:\\\\/i';

my $tel_conn = new Net::Telnet ( Timeout => $timeout,
## valid values are 'die' or 'return'
Errmode => 'return', ## TODO check this
Prompt => $prompt,
Dump_Log => 'C:\TelnetDump.txt',
Input_Log => 'C:\TelnetInput.txt',
Option_Log => 'C:\TelnetOption.txt'
);

my $hostname = 'lonsdbmis';
$tel_conn->open($hostname);
my ($username, $passwd) = @ARGV;
$tel_conn->login($username, $passwd);

my $cmdstring = q(dir > C:/testtelnet/diroutput.txt); ## How do I
capture output here ??
my $output = $tel_conn->cmd (String => $cmdstring);

#my $cmdstring = q(dir);
#my @output = $tel_conn->cmd (String => $cmdstring); ## This returns
array containing empty string

print Dumper 'Output from dir command';
print Dumper $output;
#print Dumper \@output;

$tel_conn->close();

exit(0);
 
Ad

Advertisements

L

l v

I'm using Net::Telnet for the first time.

I would like to run a command on a remote windows machine and have been
experimenting with the Net::Telnet module.

The attached test code seems to work - It just executes 'dir' on the
remote machine and redirects the output to the file.

However I want to be able to capture the output from the remote command
I am running directly rather than have to write it to an intermediate
file.

I thought I could replace this

my $cmdstring = q(dir > C:/testtelnet/diroutput.txt); ## How do I
capture output here ??
my $output = $tel_conn->cmd (String => $cmdstring);

with
my $cmdstring = q(dir);
my @output = $tel_conn->cmd (String => $cmdstring);

but I just get an array containing an empty string.

Can someone point out where I am going wrong ? TIA
------------------------------------------------------------------------------------------------------------------------------------
use strict;
use warnings;
use Net::Telnet;
use Data::Dumper;

if($#ARGV != 1)
{
print STDERR "\nUsage $0 <username> <password>";
exit(-1);
}

my $timeout = 10;

my $prompt = '/C:\\\\/i';

my $tel_conn = new Net::Telnet ( Timeout => $timeout,
## valid values are 'die' or 'return'
Errmode => 'return', ## TODO check this
Prompt => $prompt,
Dump_Log => 'C:\TelnetDump.txt',
Input_Log => 'C:\TelnetInput.txt',
Option_Log => 'C:\TelnetOption.txt'
);

my $hostname = 'lonsdbmis';
$tel_conn->open($hostname);
my ($username, $passwd) = @ARGV;
$tel_conn->login($username, $passwd);

my $cmdstring = q(dir > C:/testtelnet/diroutput.txt); ## How do I
capture output here ??

Your output to STDOUT is redirected to a file
C:/testtelnet/diroutput.txt . You are not going to get anything back
except STDERR (I think). Just do
my $cmdstring = q(dir);
my $output = $tel_conn->cmd (String => $cmdstring);

#my $cmdstring = q(dir);
#my @output = $tel_conn->cmd (String => $cmdstring); ## This returns
array containing empty string

print Dumper 'Output from dir command';
print Dumper $output;
#print Dumper \@output;

$tel_conn->close();

exit(0);

This works for me when telneting to a AIX server.
$t = new Net::Telnet (Timeout => $secs,
Prompt => "/$serverName:.+/");
my $cmd = 'do something';
my @output = $t->cmd(String => "$cmd", Timeout => 40000);

Len
 
J

jl_post

However I want to be able to capture the output from the
remote command I am running directly rather than have
to write it to an intermediate file.


It looks like you might be confusing the system() call with
backticks (``). Type:

perldoc -q "output of a command"

at a DOS prompt to understand how to fix your problem.

I hope this helps.

-- Jean-Luc
 
N

niall.macpherson

It looks like you might be confusing the system() call with
backticks (``). Type:

No I'm not :(

I am fully conversant with system() and backticks, use them often when
I am running a system command locally and am aware that backticks
returns the output and system does not.

However here the command is being executed on a remote machine so these
calls are not relevant here
 
P

Paul Lalli

It looks like you might be confusing the system() call with
backticks (``).

Can you please explain where in the post the OP even *mentioned* a call
to system() ? If you're going to take the time to respond to a post,
please take the time to *read* the post first.

Paul Lalli
 
N

niall.macpherson

l v wrote:

Your output to STDOUT is redirected to a file
C:/testtelnet/diroutput.txt . You are not going to get anything back
except STDERR (I think).

No - redirecting it to a file did work as expected so I think the
output is going to STDOUT . I also tried redirecting stderr to stdout
using 2>&1 but still had nothing returned into @output
This works for me when telneting to a AIX server.
$t = new Net::Telnet (Timeout => $secs,
Prompt => "/$serverName:.+/");
my $cmd = 'do something';
my @output = $t->cmd(String => "$cmd", Timeout => 40000);

Len


Unfortunately I don't have access to any Unix boxes at present. Can
anyone give me an example that might work under windoze ?

Thanks
 
Ad

Advertisements

J

jl_post

Paul said:
Can you please explain where in the post the OP even *mentioned*
a call to system() ?

Well, I get confused at times, myself. I saw his line of code with
his accompanying comment:
my $cmdstring = q(dir > C:/testtelnet/diroutput.txt); ## How do I
capture output here ??

and I mistakenly thought he was trying to capture that output using a
system() call.
If you're going to take the time to respond to a post,
please take the time to *read* the post first.

That's good advice... I did read the message (obviously not
carefully enough), but I do make mistakes occasionally. This happens
to be one of them. (Please forgive me.)

-- Jean-Luc
 
J

jl_post

I am fully conversant with system() and backticks, use them often when
I am running a system command locally and am aware that backticks
returns the output and system does not.

However here the command is being executed on a remote machine so
these calls are not relevant here


You're right. Sorry about that.
my $output = $tel_conn->cmd (String => $cmdstring);

Well, reading through "perldoc Net::Telnet" I see this following
block of text:
In a scalar context, the characters read from the remote side are
discarded and 1 is returned on success. On time-out, eof, or other
failures, the error mode action is performed. See "errmode()".

In a list context, just the output generated by the command is
returned, one line per element.

Basically, you do not want to invoke $tel_conn() in scalar context
if you want to capture the output of the command. I know you've tried
it in list context, since I see that you have written the following
line:

#my @output = $tel_conn->cmd (String => $cmdstring);

and you mentioned that it returns an array containing an empty string.

According to the perldoc, you get this if the command happens to
return no output. Since it seems unlikely that a 'dir' command should
have no output, you might want to try to see if any other commands
work. You might want to try:

my @output = $tel_conn->cmd("echo hello");

Does this return anything? If you want another suggestion, you might
want to try calling the ::cmd() mthod with only one argument. (I know
this sounds odd, but I've had modules react differently depending on
the case of the parameter key -- that is, the perldoc shows it starting
with a capital letter but it only works for me with a lowercase
letter.)

I doubt this'll help, but you might want to give it a shot.

-- Jean-Luc
 
L

l v

l v wrote:





No - redirecting it to a file did work as expected so I think the
output is going to STDOUT . I also tried redirecting stderr to stdout
using 2>&1 but still had nothing returned into @output

No - you've redirected STDOUT to a file, therefore there is nothing to
return to Net::Telnet.
From Net::Telnet docs:
In a scalar context the characters read are discarded and a boolean is
returned indicating the success or failure of sending the command
string and reading the prompt. Note that in order to return on error,
errmode() must not be set to "die".

In an array context, just the output generated by the command is
returned, one line per element. In other words, all the characters in
between the echoed back command string and the prompt are returned. *If
the command happens to return no output, an array containing one
element, the null string is returned.* This is so the array will
indicate true in a boolean context.

Reread the following -> "If the command happens to return no output, an
array containing one element, the null string is returned."

By you redirecting the output to a file, there is no output returned.

Since you do not want to use and intermediate
file, try it without the redirect into an array and see what you get.

Unfortunately I don't have access to any Unix boxes at present. Can
anyone give me an example that might work under windoze ?

Irrelevant, telneting to windows vs unix would work the same regarding
returning output from the remote command.
 
N

niall.macpherson

l said:
Reread the following -> "If the command happens to return no output, an
array containing one element, the null string is returned."

I do appreciate this - redirecting to a file was just a method to
ensure that the 'dir' was returning some data.Once I had established
this I tried to revert to the

my $cmdstring = q(dir);
my @output = $tel_conn->cmd (String => $cmdstring); ## This returns
array contining empty string

code which is where I hit the problem of not gatting data back whch I
am still trying to resolve
Irrelevant, telneting to windows vs unix would work the same regarding
returning output from the remote command.

I do see that it should work the same. However there is a section in
the perldoc page headed 'Connecting to a Remote MS-WIndows Machine'
which talks about 'false telnet servers' and made me wonder whether
this is a problem. Unfortunately the machine I am trying to retrieve
info from is a customer's machine across a VPN and I will not be
permitted to install another telnet server there.
 
N

niall.macpherson

(e-mail address removed) wrote:

.. You might want to try:
my @output = $tel_conn->cmd("echo hello");

Does this return anything? If you want another suggestion, you might
want to try calling the ::cmd() mthod with only one argument. (I know
this sounds odd, but I've had modules react differently depending on
the case of the parameter key -- that is, the perldoc shows it starting
with a capital letter but it only works for me with a lowercase
letter.)

I doubt this'll help, but you might want to give it a shot.

-- Jean-Luc

Am afraid I still get an array containing a single empty string :(

Code changed as follows

my @output = $tel_conn->cmd ("echo hello");
print Dumper 'Output from echo command';
print Dumper \@output;

produces the following output

$VAR1 = 'Output from echo command';
$VAR1 = [
''
];

In the dump file (specified by the Dump_Log parameter when creating the
initial telnet object) I see the following
0x00000: 65 63 68 6f 20 68 65 6c 6c 6f 0d 0a echo hello..

< 0x00000: 1b 5b 34 3b 35 48 65 63 68 6f 20 68 65 6c 6c 6f
..[4;5Hecho hello
< 0x00010: 1b 5b 35 3b 31 48 68 65 6c 6c 6f 1b 5b 37 3b 31
..[5;1Hhello.[7;1
< 0x00020: 48 43 3a 5c 3e 1b 5b 37 3b 35 48
HC:\>.[7;5H

so it does appear that the command is executing successfully.

Re using only one argument - can't think of too many commands which
take no parameters other than dir. I have tried

my @output = $tel_conn->cmd ("help");

and with redirecting stderr

my @output = $tel_conn->cmd ("help 2>&1");

For both of these I end up with slightly different (but equally
useless) output as from the dir command - in both cases an empty array
rather than an array containing one empty string

$VAR1 = 'Output from help command';
$VAR1 = [];

This one has me really stumped :(
 
Ad

Advertisements

N

niall.macpherson

However I want to be able to capture the output from the remote command
I am running directly rather than have to write it to an intermediate
file.

I thought I could replace this

my $cmdstring = q(dir > C:/testtelnet/diroutput.txt); ## How do I
capture output here ??
my $output = $tel_conn->cmd (String => $cmdstring);

with
my $cmdstring = q(dir);
my @output = $tel_conn->cmd (String => $cmdstring);

After some further experimentation it appears that the remote machine
may not be flushing the ouput.

Immediately after getting the output back into @output as above I tried
the following

print Dumper 'EOF', $tel_conn->eof;

This gave an empty string for eof which indicates there is still data
to be read.

I therefore tried the getline() and getlines() methods

while(! $tel_conn->eof )
{
my $line = $tel_conn->getline( Timeout => 60 );
print Dumper $line;
}

and

while(! $tel_conn->eof )
{
my @lines = $tel_conn->getlines( Timeout => 60 );
print Dumper @getlines;
}

but both died with the following
read timed-out at C:\develop\NiallPerlScripts\telnet.pl line 46

(btw I have also changed Errmode=>return to Errmode=>die in the
$tel_conn constructor call )
 
N

niall.macpherson

while(! $tel_conn->eof )
{
my @lines = $tel_conn->getlines( Timeout => 60 );
print Dumper @getlines;
}

Correction , should of course read

while(! $tel_conn->eof )
{
my @lines = $tel_conn->getlines( Timeout => 60 );
print Dumper @lines;
# ^^^^^^^^^
}
 
C

cmic

Hi Niall

One [trivial ?] question : have you tried to telnet directly to this
host and see if the DIR command yields something ? An what is the
output ?
Sorry if I mess....

PS : I'm gonna try this Telnet::Cmd module at the office. Wanna see...
 
C

cmic

Hello Niall

(e-mail address removed) a écrit :
(e-mail address removed) wrote:

. You might want to try: snip....

In the dump file (specified by the Dump_Log parameter when creating the
initial telnet object) I see the following
0x00000: 65 63 68 6f 20 68 65 6c 6c 6f 0d 0a echo hello...

< 0x00000: 1b 5b 34 3b 35 48 65 63 68 6f 20 68 65 6c 6c 6f
.[4;5Hecho hello
< 0x00010: 1b 5b 35 3b 31 48 68 65 6c 6c 6f 1b 5b 37 3b 31
.[5;1Hhello.[7;1
< 0x00020: 48 43 3a 5c 3e 1b 5b 37 3b 35 48
HC:\>.[7;5H

Here is the point. The Net::Telnet doc says :

"Connecting Net::Telnet to one of these false TELNET servers makes your
job of parsing command output very difficult. It's better to replace
a
false TELNET server with a real TELNET server. The better TELNET
servers for MS-Windows allow you to avoid the ANSI escapes by turning
off something some of them call console mode."

As I understand, you execute your Perl script on a Windows host and
connect to a Windows host on which a telnet server is running. The
Dump_Log shows many
escape sequences (1B 5B ...) which are described in the Net:Telnet doc
as "makes your
job of parsing command output very difficult". If I'm not wrong, you
have to extract a correct prompt from this mess to put it on the
Net:Telnet object. Or install a *real* telnet server. But it seems you
can't...

Sorry if this doesn't help.
Regards
--
cmic
so it does appear that the command is executing successfully.

Re using only one argument - can't think of too many commands which
take no parameters other than dir. I have tried

my @output = $tel_conn->cmd ("help");

and with redirecting stderr

my @output = $tel_conn->cmd ("help 2>&1");

For both of these I end up with slightly different (but equally
useless) output as from the dir command - in both cases an empty array
rather than an array containing one empty string

$VAR1 = 'Output from help command';
$VAR1 = [];

This one has me really stumped :(
 
Ad

Advertisements

N

niall.macpherson

cmic said:
Hi Niall

One [trivial ?] question : have you tried to telnet directly to this
host and see if the DIR command yields something ? An what is the
output ?
Sorry if I mess....
Hi cmic.

Yes telnet from the cmdline works fine.

I have since made a bit of progress. Although I still cannot get any
data from the getline() / getlines() methods, I managed to work out
that the data was getting back to me from the server.

I established this by the following

my $results = $tel_conn->buffer;

This produced the required results from the 'dir' command (admittedly
containing all the ANSI terminal escape sequences which I had to
remove) I then just call

$tel_conn->buffer_empty()

before making the next call to $tel_conn->cmd().

Seems a bit klugy but it gives the required results so I am going to
use this in order to get my code tested and out and then try to figure
out a better way later.
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top