nmorenod has asked for the wisdom of the Perl Monks concerning the following question:

First message here, after spending some days reading other posts related. I have a comment... this page is huge! HUGE! congratulations!

I have bought a device which I want to control remotely. The only way to do this is establishing an SSH-2 connection as a client with the device (that has an SSH-2 server implemented on it). If I do this from Linux with the ssh command, a shell is displayed where I can type commands and read the answer. I would like to use Perl to automatize its control.

This device answers to the commands first with an acknowledgment: for example, an empty line and "ok,00" is the right one. After that, it adds in some cases an status message giving some information to control it. Sometimes these information messages are sent asynchronously (without sending any command), keeping the same format. Here is an example (in this case the first command is written by me and the second "empty command" is written automatically by the device to report the status).

$ control sleep ok,00 $ ok,00 SS,true

My problem is the following: when I use the corresponding package in Perl (I've tried with Net::SSH::Perl, Net::SSH2 and Net::OpenSSH) to establish the connection and send the commands, everything works fine except for one thing; the output retrieved (found either with the command output or with a handler) only contains the acknowledgment, ignoring the status message. It happens the same for the 3 packages mentioned.

After doing many tests, I think that maybe is a problem of the format in which this status message is sent. But it's really strange that it's perfectly shown when using a shell and it disappears when using any of the mentioned packages. Probably the SSH-clients used in these packages close the channel once the ACK is received.

Here I paste the log of a SSH2-client (putty) for a command, starting with the prompt ($) and ending with the answer and the status message:

Incoming packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 01 00 00 00 00 02 24 20 ........$ Outgoing packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 00 00 00 00 00 01 63 ........c Incoming packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 01 00 00 00 00 01 63 ........c Outgoing packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 00 00 00 00 00 01 6f ........o Incoming packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 01 00 00 00 00 01 6f ........o . . . ------------------ (Here continues the command) ---------------------- ------------------ (until it finishes) ---------------------- . . . Outgoing packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 00 00 00 00 00 01 0d ......... Incoming packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 01 00 00 00 00 02 0d 0a .......... Incoming packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 01 00 00 00 00 02 0d 0a .......... Incoming packet type 94 / 0x5e (SSH2_MSG_CHANNEL_DATA) 00000000 00 00 01 00 00 00 00 45 6f 6b 2c 30 30 0d 0a 43 .......Eok, +00..C 00000010 53 2c 31 31 2c 31 2c 44 69 61 6c 69 6e 67 2c 41 S,11,1,Dial +ing,A 00000020 75 64 69 6f 2c 4e 6f 72 6d 61 6c 2c 31 34 39 2e udio,Normal +,149.

If someone has managed to read this boring problem up to this point, I am already thankful! But any help would be a great one! How can I get the status message? Thanks in advance :)

Replies are listed 'Best First'.
Re: Retrieving status data from a device with SSH 2 using Perl
by zentara (Cardinal) on Feb 16, 2010 at 17:21 UTC
Re: Retrieving status data from a device with SSH 2 using Perl
by salva (Canon) on Feb 16, 2010 at 19:08 UTC
    You are probably suffering a variation of the problem described in Re: Unable to run command on Cisco switch. In this case, you get different output when you run commands in interactive mode (through the shell) than when you run them directly from the SSH command line (or through a Perl module, it's the same).

    If you really need those codes use Expect (alone, wrapped by Net::SSH::Expect or combined with Net::OpenSSH) to interact with a shell on the remote device.

      Yes... probably there are different modes. Is there a way to make the server give the answers to the commands as if they were written using the shell?

      For this solution you suggest with Expect, should I use it directly with the shell executing ssh from the Perl script? Because I guess that if I use Expect with the Net::OpenSSH commands, I have to work with the same incomplete answer as if I were using the commands directly.

      Thanks again!

      PS: Salva? Betanzos? Super López? I guess I'm not the only Spaniard here!

        Because I guess that if I use Expect with the Net::OpenSSH commands, I have to work with the same incomplete answer as if I were using the commands directly.

        You can use Net::OpenSSH to establish the connection to the remote machine and then run an interactive shell managed with Expect as follows:

        my ($pty, $pid) = $ssh->open2pty() # and empty command line invokes a +shell! or die "unable to run remote shell"; my $expect = Expect->init($pty); $expect-> ...
        Though, if that is all you need to do in the remote server, using Expect alone will be almost the same, the only difference is that you will have to take care of authentication also.
        PS: Salva? Betanzos? Super López? I guess I'm not the only Spaniard here!

        No, you are not, where are you from?

Re: Retrieving status data from a device with SSH 2 using Perl
by Corion (Patriarch) on Feb 16, 2010 at 16:59 UTC

    Can you please post (the relevant parts of) your code?

      I am really astonished with all the fast answers. Thanks to all of you!

      Here is an example of the code, using Net::OpenSSH (the results with the other packages are similar):

      my $ssh = Net::OpenSSH->new($host, "user"=>$user, "passwd"=>$pass); $ssh->error and die "Couldn't establish connection: ". $ssh->error; my @output = $ssh->capture('control call dial $receiver'); $ssh->error and warn "Couldn't make the call: ". $ssh->error; print "line: $_" for (@output); sleep(1); my @output = $ssh->capture('control call hangup -a'); $ssh->error and warn "Couldn't hangup: ". $ssh->error; print "line: $_" for (@output);

      With this, I get the following output printed:

      line: line: ok,00 line: line: ok,00

      And this is the same but using the shell with the ssh command:

      $ control call dial *receiver* ok,00 CS,23,1,Dialing $ control call hangup -a ok,00 CS,23,1,Terminated $
Re: Retrieving status data from a device with SSH 2 using Perl
by Anonymous Monk on Feb 16, 2010 at 17:37 UTC
    Try to use Term::Expect for automation