There was, many times repeated, question on GroupStudy today.
How do I deploy my changes on many routers? Are there any tools that do that?
The answer to that question is - sure there are. Many of them. Some cost money, some are free, some offer good change control, rollback, etc. What is common with all of them is that often, one doesn't have the luxury of having them around when one needs them. For those cases, something quick-and-dirty just may be enough. The Perl script below does just that. It will pick up the list of commands to run from a file, it will pick up the list of routers from another file. It will then telnet to all routers in sequence and deploy your set of commands. There is very rudimentary error checking, so... use at your own risk.
This has been written in 15 minutes and is probably full of bugs and really bad code, but... it works for me.
#!/usr/bin/perl -w
use Net::Telnet::Cisco();
use strict;
my ($host, $user, $pass, $enab, $cmdf, $lstf, @cmds);
$cmdf = "commands.txt";
$lstf = "list.txt";
$user = "USERNAME";
$pass = "PASSWORD";
$enab = "ENABLE_PASSWORD";
sub ConfigureRouter {
my ($t, $host, $cmd);
$host = $_[0];
if (!($t = Net::Telnet::Cisco->new(Host => "$host", Errmode => "return"))) {
printf("Could not open session to '%s'\n", $host);
return;
};
if (!($t->login($user, $pass))) {
printf("Could not log into '%s' as '%s'\n", $host, $user);
return;
}
$t->enable($enab);
print("Login successful. Setting up ");
$t->print("terminal length 0");
print $t->waitfor("/#/");
$t->print("conf t");
foreach $cmd (@cmds) {
print $t->waitfor("/#/");
$t->printf("%s", $cmd);
}
print $t->waitfor("/#/");
$t->print("end");
print $t->waitfor("/#/");
$t->print("write memory");
print $t->waitfor("/#/");
$t->close();
}
#
# Main Body
#
open (CF, "< " . $cmdf) or die "Can't read the command file '$cmdf'";
@cmds = <CF>;
close(CF);
open (IF, "< " . $lstf) or die "Can't read the router list file '$lstf'";
while (defined ($host = <IF>)) {
chomp($host);
if ($host ne "") {
printf("\n\n\n%s %s %s\n", "-" x 22, $host, "-" x 22);
ConfigureRouter($host);
}
}
close(IF);
Did I say that you should use this at your own risk?

6 comments:
Do you know if this will work with SSH? I'm using an old unlicensed version of Winagents now and it seems to bog down my server at times.
This particular script relies on Net::Telnet package for Perl, so it won't work with SSH.
If you want to automate SSH backups, taking a look at a tool like RANCID may be a good idea.
If you want something similar but with SSH (and serial port) support, try my Perl module Net::Appliance::Session.
It's similar to the code above, but with better cross platform support and error checking. A rewrite is being worked on so feedback and ideas would be very welcome!
cheers, oliver.
Or simply use the Expect CPAN to use SSH. You don't *have* to use the Cisco style CPAN.
http://newenglandnetworkconsulting.com/
http://gunnim.blogspot.com/
the device-commander is similar in theory to marko's perl sript. It's written in python and depends on the pexpect module. It has some inbuilt error handling and supports both SSH and telnet devices + handles commands that expect input from the user due to usage of the python expect module.
I'd second Expect, works nicely to me with SSH client invoke.
#!/usr/bin/perl
use strict;
use Expect;
my $ssh = "/usr/bin/ssh";
my $user = "user";
my $pass = "user_pwd";
my $enable = "enable_pwd";
my $timeout = 10;
my $host = shift (@ARGV);
if (! $host) {
print "Usage: ct host [ command ]\n";
exit;
};
my $cmd = join(" ", @ARGV);
my $exp = Expect->spawn($ssh, "$user\@$host")
or die "Cannot spawn $ssh: $!\n";
$exp->expect($timeout, "assword:");
$exp->send("$pass\n");
$exp->expect($timeout, ">");
$exp->send("enable\n");
$exp->expect($timeout, "assword:");
$exp->send("$enable\n");
$exp->expect($timeout, "#");
if ($cmd) {
$exp->send("$cmd\n");
$exp->expect($timeout, [ "<--- More --->", sub { my $self = shift;
$self->send(" ");
exp_continue; } ],
'-re', qr'# $', );
} else {
$exp->interact();
};
Cheers,
Alexei.
Post a Comment