http://www.perlmonks.org?node_id=959817

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

Hi monks, I'm brand new to coding (under a month's worth) and have found this site to be one of my gotos for info. The script I'm attempting to write establishes a telnet connection to an HP Procurve switch, reboots it, accesses it's extended boot menu, clears out all but it's basic files and reboots the switch. I'm running into a snag when I issue a command to list all current files (which is ls for this switch) I'm trying to capture the output into a string or an array, but it doesn't capture anything. the command is issued while watching the switch and I can see it list all the files, but the string or array I tell it to dump to is empty. below is the code focusing on getting the info into the array. Any and all help would be greatly appreciated.

#!/usr/bin/perl $| = 1; use Net::Telnet; use strict; use CGI; use warnings; print("content-type: text/html\n\n"); my $console_server = ('TRN-13-MRV-CON-07'); my $console_mgmtA = ('2013'); my $match; my $garbage; my $output; my @array; establishing Telnet connection my $telnet = new Net::Telnet (Timeout=>10, Errmode=>'return', Port => +$console_mgmtA); $telnet->open($console_server); $telnet->put(chr(13)); sleep(1); $output=$telnet->cmd('ls'); #to see what's in the string print("$output\n"); #take the string and create an array @array = split("\n",$output); #see what's in the array print @array; exit;

Replies are listed 'Best First'.
Re: Need help getting output from Telnet into a string or array
by samtregar (Abbot) on Mar 15, 2012 at 17:09 UTC

    Here's the lines from Net::Telnet's docs for the cmd() method that explain what's happening:

    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. 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, a list containing one element, the empty string is returned. This is so the list will indicate true in a boolean context. On time-out, eof, or other failures, the error mode action is performed. See errmode().

    So you need to call it in list context if you want the output (assign the result to @array, not a scalar like $output).

    -sam

    PS: For a brand new coder your code-quality looks great!

      Thanks for your post. I guess I missed that tidbit of info. I can see it pass the 1 when I query the string. I modified my call line to the following

      @array=$telnet->cmd(string => 'ls', prompt => '/=>/');

      to explain the prompt tag, I found the following tidbit of info

      To run a program and gather its output, use the cmd method. Pass it the string to send; it returns the command output as one line per list element in list context, or as one long line in scalar context. It waits for the Prompt before returning.

      my array is still coming back empty, I'm guessing I'm not passing the information via a list context, so how would I go about doing it? Thanks again for all your help!

        I looks like someone else has done similar work.. In their example, they used:

         Prompt     => '/'.$switch.'.*?# /',

        ... where $switch is the name of the switch ... so the text of the prompt would be the switchname and maybe something else, ending in '# '

        ... but they also had to do extra checking to deal with some other differences between software versions, so this may be a more complex beast to deal with. Odds are, with any piece of networking gear that's out there, someone's already figured out how to interact with in in Perl, even if it means screen scraping HTML GUIs, so it's worth searching for "(hardware name) perl" in your preferred search engine.

        Is the prompt actually /=>/? That's an odd prompt. Maybe you should try '=>'? Or perhaps qr/=>/ if it's expecting a regex.

        I don't know if this will be more distracting than useful, but if I was coding this I would use Expect. It takes a little getting used to but it has great debugging features.

        -sam

      Success! Kinda... Working on this for the last 4 hours and I've came up with a result. When I issue my line
      @array=$telnet->cmd(string => 'ls', prompt => '/=>/');
      it STOPS at the first prompt where the ls is being issued. I changed my code to
      @array=$telnet->cmd(string => 'ls', prompt =>'/ls/');
      my output is => (the prompt before the ls). I tested this with another switch which has a different output and had a unique word in it (free) and it produced all info up to that word which is what I believe it's supposed to do. Now I guess what my question is, why is my cmd picking up the first prompt and not the second after the output? Thanks
        If your primary concern here is controlling the switch(es), not just dabbling with Perl for Perl's sake, I recommend looking at Rancid. It offers script wrappers for various vendors and models. You only supply the device command sequence, the scripts deal with login, prompts, output redirection etc.