http://qs321.pair.com?node_id=603305

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

I am having a frustrating problem extracting information from routers and switches. I have tried several variations of code, but for some reason, I am not getting any results in my variables. Here is a code snippet.
my @results = $telnetvar->cmd(String => 'show version', Prompt => '/#/') ;
I have verified that the script opens the connection to the device, and authenticates. For whatever reason, when I try to print out the @results, like follows
foreach $resultline (@results) { print OUTPUT "$resultline\n"; }
I never get any results in $resultline I have written similar code elsewhere, and it still works, yet this is not working. I've tried it using activePerl 5.8 on both Windows and Unix (Sun), and using Perl 5.003 on Unix, and also using the Net::Telnet and even the Net::Telnet::Cisco mods. No luck. Any ideas on what I can try next? Thanks

Replies are listed 'Best First'.
Re: Net::Telnet on routers and switches
by rodion (Chaplain) on Mar 06, 2007 at 01:59 UTC
    If you're not using it already, you should definitely get quite familiar with looking at the file generated by the input_log($fileName) method. This allows you to see what happens to a session. You can see what the program had seen at the point where it timed out. I found that often, what I thought the program was waiting on was not what it was actually waiting on.

    Good luck. It's a maddenly tricky way to get data, but when it's the only way, it does beat the alternatives.

Re: Net::Telnet on routers and switches
by quester (Vicar) on Mar 06, 2007 at 06:51 UTC
    This might seem a bit off topic in Perlmonks, but I find life with Cisco is much easier using an Expect script called clogin that is part of the Rancid package, from http://www.shrubbery.net/rancid/.

    To use it, you need to install Expect; not Perl's Expect.pm, but the TCL-centric language Expect that was originally from http://expect.nist.gov/. Be sure to install Shrubbery's patched Expect; otherwise you are likely to experience processes that hang once in a blue moon for no obvious reason. It will use the built in telnet and/or ssh commands on your system.

    Clogin's configuration file is manna from heaven if your devices are the typical motley mix of different generations of equipment: some accepting telnet only, some accepting ssh only, some wanting user name and password, some wanting just the enable password twice, and some that want to autoenable (you get the # enable prompt as soon as you are logged in.)

    If you just need to issue a single command, or a canned string of commands from the command line,

        clogin -c "show clock; show version" cisco2500a

    is sufficient, once you have set up a ~/.cloginrc file to specify the characteristics of your routers. You can of course use open $fh, "clogin ...|" to read the output with a Perl script.

    If you have to look at the output of some of the commands in order to decide what the next command should be, I think that using Perl's Expect.pm to spawn clogin is far less painless painful than anything else I've seen. You just let clogin do the tedious grunt work of getting logged in and getting an enable prompt, so you can concentrate on the task at hand. (Update: fixed "less painful". Thanks, rodion!)

      This is an example of how Expect.pm and clogin can be used together:

      #! /usr/bin/perl -w use warnings; use diagnostics; use strict; use Expect qw(expect); use Carp; scalar @ARGV or croak "usage: $0 host1..."; my $session = Expect->spawn( 'clogin', $ARGV[0] ); if ( exists $ENV{'exp_internal'} ) { $session->exp_internal(1) } $session->log_stdout(1); sub expect_send { my $pattern = shift; my $command = shift; my $ret = $session->expect( 30, [ '-re', $pattern => sub { $_[0]->send("$command\n") } ], @_, [ timeout => sub { croak 'Timeout' } ], [ eof => sub { croak 'EOF (clogin exited unexpectedly)' } +], ); croak 'Nothing matched, not even timeout, died' if not defined $ret; return $ret; } expect_send qr/#/, 'show clock'; expect_send qr/#/, 'show logging'; $session->expect( 30, [ '-re', qr/Log Buffer \(\d+ bytes\)/i => sub { $session->match() =~ /\((\d+) bytes\)/i; print "\n\n* Found logging buffer size is $1 bytes *\n\n"; if ( $1 < 8192 ) { expect_send qr/#/, 'configure terminal'; expect_send qr/\(config\)#/i, 'logging buffered 8192'; expect_send qr/\(config\)#/i, 'end'; expect_send qr/#/, 'write memory'; } } ], ); expect_send qr/#/, 'exit'; $session->soft_close;
Re:Net::Telnet on routers and switches
by traveler (Parson) on Mar 05, 2007 at 22:55 UTC
    I have never needed to set the Prompt. It seems you could use the default.

    Check the manual for information on debugging (check the cmd section in particular). I suspect you are timing out.

Re: Net::Telnet on routers and switches
by jasonk (Parson) on Mar 06, 2007 at 11:58 UTC

    For reasons I never took the time to fully investigate, I could never get Net::Telnet or Net::Telnet::Cisco to work for this either. Since I was short on time I ended up using Expect to automate a real telnet process, and in the end this worked better than the original plan anyway (among other things, when I ran into a switch that had telnet access disabled and only allowed access via ssh, it was a one-line change to make the command that the script called be configurable).


    We're not surrounded, we're in a target-rich environment!
      Thanks for all the replies. I was able to get it to work, by modifying the Prompt setting on the cmd call. For some reason, this prompt setting did not work,
      Prompt => '/[>|#|\)|:]\s*$|\s/'
      although it works elsewhere using the same method. Not sure I understand why, but my experience is that Perl is funny that way. Anyway, I was able to use
      Prompt => '/#/'
      I will have to expand on that for the 1% of devices whose prompts are not standard for our environment. Thanks again