Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

comment on

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

This is a script for reading config info from a bunch of routers (for archiving, autiting, whatever)

The configuration for the script itself is read from a INI-style config file (example below). Each router is represented by a section with its name or IP as the section header. The "info" attribute is mandatory (originally intended as title information for a to-be-generated report). Then there has to be a section "dump" (which means if you have a router with a hostname of "dump", you have to refer to it by its IP address).

Each entry in the "dump" section results in a command sent to the router(s), and the output of this command is written to a file.

The output is placed in the directory named by "dir" in the top INI section. Each router gets its own subdirectory, and if set "debug", there will be a subdirectory "debug" - so you should not use "debug" as hostname, either :-)

The "enable" password is needed, because on Cisco devices, the terminal size command is privileged.

Initially, I used Net::Telnet::Cisco, and later adapted it for SSH. After trying with SSH modules directly, I settled with Control::CLI. It took me a while noticing that they use different ways of to specify prompts, before getting it to work.

Of course it is bad to have passwords stored as plaintext, but at least they are kept separate from the script itself. It runs under Windows, but should work under other systems, too.

Additionally, I uploaded it to a github gist, just in case someone wants to tinker.

use strict; use warnings; use Data::Dumper; use Config::Tiny; use Path::Tiny 'path'; binmode STDOUT, ':encoding(cp437)'; use Control::CLI; my $ini = Config::Tiny->read( 'ciscodump.ini' ); my $dumpdir = path($ini->{_}{dir}); my $debugdir = $dumpdir->child('debug'); my $debug = $ini->{_}{debug}; $Data::Dumper::Useqq = 1; sub dbg { print @_ if $debug; @_; } dbg Dumper $ini; my @k = grep { $_ !~ /^(_|dump)$/ } keys %$ini; print Dumper \@k if $debug; my %dumpcommands = %{$ini->{dump}}; my $prompt = '(?m:^\W?(?!Device#)[\w\/\d.:-]+[>#])'; my %cs_opts; $cs_opts{Prompt} = $prompt; $cs_opts{Errmode} = 'return'; $cs_opts{Output_record_separator} = "\r"; for my $host (@k) { my $user = $ini->{$host}{user} // $ini->{_}{user}; my $pass = $ini->{$host}{pass} // $ini->{_}{pass}; my $enable = $ini->{$host}{enable} // $ini->{_}{enable}; my $info = $ini->{$host}{info} // $ini->{_}{info}; my $method = $ini->{$host}{use} // 'SSH'; print "$host\t- $info\n"; $debug = $ini->{_}{debug} // $ini->{$host}{debug}; $debugdir->mkpath if $debug; $cs_opts{Dump_Log} = $debugdir->child($host . '.log')->stringify i +f $debug; $cs_opts{Timeout} = $ini->{$host}{timeout} // 10; my $hostdir = $dumpdir->child($host); $hostdir->mkpath; my $cc = Control::CLI->new( %cs_opts, Use => $method ); my %login_opts = ( Username => $user, Password => $pass, ); if ($method =~ /^TELNET$/i) { if ($cc->connect(Host => $host)) { dbg "TELNET connection established\n"; if ($cc->login(%login_opts)) { dbg "logged in\n"; } else { warn 'login failed: ' . $cc->errmsg(); } } else { warn 'connection could not be established: ' . $cc->er +rmsg(); next; } } else { # SSH if ($cc->connect(Host => $host, %login_opts)) { dbg "SSH connection established\n"; } else { warn 'connection could not be established: ' . $cc->er +rmsg(); next; } } dbg Dumper $cc->read(Blocking => 1, Timeout => 5); dbg "enable>\n"; dbg Dumper $cc->cmd(command => 'enable', prompt => 'Password:' +); # dbg "waiting>\n"; # my @wf = $cc->waitfor(Match => 'Password:'); # dbg Dumper \@wf; dbg "sending>\n"; dbg Dumper $cc->cmd($enable); dbg "after>\n"; my $out = $cc->cmd('term len 0'); dbg Dumper $out; dbg Dumper $cc->cmd('term page 0') if grep { /invalid/i } $out +; for my $prefix (keys %dumpcommands) { my $cmd = $dumpcommands{$prefix}; dbg "command: '$cmd'\n"; my $out = $cc->cmd($cmd); dbg Dumper \$out; $hostdir->child($prefix . '.txt')->spew_raw($out); } $cc->disconnect; };
And here is the INI file example
user=admin pass=confidential enable=top_secret dir=C:\Users\Administrator\Desktop\ciscodump [dump] inventory=show inventory version=show version running-config=show running-config startup-config=show startup-config [] info=location with different parameters user=otheruser pass=public timeout=30 [] info=somewhere else, but "central" parameters [] info=ancient router use=TELNET [] debug=yes info=lets see...

In reply to ciscodump - dump config info from routers into files by soonix

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 the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others pondering the Monastery: (3)
    As of 2021-04-11 23:55 GMT
    Find Nodes?
      Voting Booth?

      No recent polls found