Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

I would like to connect from Windows XP to SSH2 server and from there establish a telnet connection to device. I would like to send a command to this device, wait expected prompt from the telnet session over SSH connection and read the result. So far best results have been with Net::SSH2. The problem is the telnet connection.

The problem is that after I issue 'telnet <IP Address>' command, I cannot read the data without breaking the command sending/reading. If I read the result once after telnet has been established, I get after that only the command that was sent. For example after sending the telnet command, I read the result to look for username prompt and send the username. After this I get only the username that was sent as a result, not the actual output. Seems like output and input are mixed after first read.

I can issue the commands over telnet session quite nicely if I do not read the results at all. But unfortunately, I need to parse the output and decide following actions based on collected data. This might be possible with several sequential sessions, but I am looking send command, wait expected data and read response type of solution on Windows machine. I am trying to compile this as executable with ActiveState tools and for this reason I don't think that Cygwin is an option.

Is there a way to do this on Windows machine? Is this somehow related to terminal settings that I should modify before establishing the telnet session? Newbie question, but I was not able to find the module where implementation of $channel->read() really is?

Thank You
#!/usr/bin/perl # Tested with ActiveState perl version 5.8.8 on Windows XP SP3. use strict; use warnings; use Net::SSH2; # Using version 0.28. use Data::Dumper; #Net::SSH2->debug(1); use constant NEWLINE => qq{\n}; my $g_ssh_server = '<>'; # SSH server addresss my $g_username = '<username>'; my $g_password = '<password>'; my $g_prompt = '<ssh server prompt>'; my $g_telnet_cmd = 'telnet <>'; # Command to telnet my $g_ssh = undef; my $g_channel = undef; # Connection opened with shell. SSH2Open(\$g_ssh, \$g_channel); # Separate commands are executed and read nicely. SSH2Send($g_ssh, $g_channel, "\n", $g_prompt); SSH2Send($g_ssh, $g_channel, 'ls -al', $g_prompt); SSH2Send($g_ssh, $g_channel, 'uname -a', $g_prompt); SSH2Send($g_ssh, $g_channel, 'ls -l', $g_prompt); # Starting telnet causes problems if command output is read SSH2Send($g_ssh, $g_channel, $g_telnet_cmd, '<expect username prom>'); SSH2Send($g_ssh, $g_channel, 'username', '<expect password prom>'); SSH2Send($g_ssh, $g_channel, 'passowrd', '<expect terminal prom>'); SSH2Send($g_ssh, $g_channel, 'ls -al', '<expect terminal prom>'); # Read to test commands without reading after each command. SSH2Read($g_ssh, $g_channel); sub SSH2Open{ my $ssh2 = shift; # OUT my $channel = shift; # OUT ${$ssh2} = Net::SSH2->new(); ${$ssh2}->connect($g_ssh_server) or die $!; ${$ssh2}->auth_password($g_username, $g_password) or die 'Auth. Fail +ed'; ${$channel} = ${$ssh2}->channel(); ${$channel}->pty('vt80'); # To get the prompt also. ${$channel}->shell(); return; } sub SSH2Send{ my $ssh = shift; # IN my $channel = shift; # IN - Created channel my $command = shift; # IN - Command to be sent my $waitfor = shift; # IN - String to be waited for. my $found = 0; my $string = q{}; my @result = (); print "===============================\n"; print "send command ($command)\n"; $channel->write(($command . NEWLINE)); if(0) { # Read response with method 1. This works randomly depending on # latency I quess. This may not read all of the data or last # command reads the data for every command. $string = q{}; while( <$channel> ) { $string = $string . $_; } } if(0) { # Read response with method 2. same as method 1. $string = q{}; my @result = readline($channel); $string = $string . join("\n", @result); } # Read response with method 3. Try polling until requested prompt # found. Based on if(1) { my( $n, $buffer ); my @poll = ({handle => $channel, events => ['in', 'ext', 'err']}); $string = q{}; $channel->blocking(0); while(not $channel->eof and not $found) { $ssh->poll( 2000, [ @poll ] ); # 2 seconds print "poll" . Dumper \@poll; foreach my $poll ( @poll ) { foreach my $event ( qw( in ext ) ) { next unless $poll->{revents}{$event}; if($n = $channel->read( $buffer, 10_240, $event eq 'ext' )){ $string = $string . $buffer; #print "read string ($n) - $string\n"; } # Check if the requested data was read. $found = __test_waitfor($waitfor, $string); } } } } print "response: $string\n"; print "===============================\n"; return; } sub SSH2Read{ my $ssh = shift; # IN my $channel = shift; # IN my $string = q{}; if(0) { $string = q{}; while( <$channel> ) { $string = $string . $_; } print "string $string\n"; } return; } sub __test_waitfor{ my $waitfor = shift; # IN my $string = shift; # IN my $last_line = q{}; my $found = 0; # If user defined waitfor, it is checked from last line of the # string. Otherwise the string is just tested for couple of # characters. if( $waitfor ) { ($last_line) = $string =~ m/\n?(.*)\z/x; if( $last_line ) { print "last line ($last_line) wait ($waitfor)\n"; if( $last_line =~ m/$waitfor/ ) { $found = 1; } } } elsif( 5 < length $string ) { $found = 1; } return $found; }

In reply to Telnet over SSH2 from Windows by Hessu

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others imbibing at the Monastery: (9)
    As of 2018-06-22 19:34 GMT
    Find Nodes?
      Voting Booth?
      Should cpanminus be part of the standard Perl release?

      Results (124 votes). Check out past polls.