Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

comment on

( [id://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 [192.168.0.1] info=location with different parameters user=otheruser pass=public timeout=30 [192.168.11.1] info=somewhere else, but "central" parameters [192.168.21.100] info=ancient router use=TELNET [192.168.254.254] debug=yes info=lets see...

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

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



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2024-04-16 14:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found