Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Comment on

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

I currently have quite alot of cisco switches and routers that I am responsible for maintaining. I got very sick of having to log into a dozen different devices to make the same changes on everyone of them.

I started playing around with perl hoping it would get the job done. I've really never done much programming in the past, aside from very simple shell scripts.

I wrote the following piece of code to simplify my life abit and am happy with how it works. I know there are some obvious security problems with it (currently I run it as root to be able to ping my targets first to verify that they are up) and there are problem several spots where I could have been much more concise.

I am basically looking for some constructive criticism on what I've got and how to improve it. Like I wrote earlier I don't have much programming experience so don't abuse me too bad.

The script takes as its first argument the name of the file that it will feed to the device it connects to. It can take as additional arguments either the name of a file full of IPs(specified with -l as the second argument) or will accept any number of IPs as arguments.

#!/usr/bin/perl -w #********************************************************************* +** #** Written to make making the same configuration changes to a number +** #** of devices less of a pain in the ass. Written with CISCO Routers +** #** and switches in mind it should work with any devices that can be +** #** sent commands via telnet. +** #********************************************************************* +** use strict; my ($script, $i, $telnetpid); unless ( @ARGV >= 2 ) { die "usage: $0 script ip ... " }#Test to verif +y that the re is the minimum number of arguments $script = $ARGV[0]; #Take the first argument as the name of the fi +le to pull commands from shift; #Remove the first argument from the list of ar +guments #Feeding a list of IPs if ( $ARGV[0] eq '-l' ){ #If the new first argument is -l we know to l +ook for a list of IPs if ( $ARGV[1] ){ #Make sure there is a list specified on the c +ommand lin e open(IPLIST, $ARGV[1]) || die "can't open $ARGV[1]\n"; while(<IPLIST>){ feedip($script, $_); } close(IPLIST) } else { die "Need to supply a list of IPs when using $ARGV[0] + \n"; } } #Feeding IPs from the command line else { foreach $i (@ARGV ) { feedip($script, $i); } } #*************************************************************** #** Subroutines below here ** #*************************************************************** #This subroutine is based heavily on code mooched from "Learning Perl" + by Randal l Schwartz and Tom Christainsen sub telnet { use IO::Socket; my ($host, $port, $kidpid, $handle, $line); unless (@_ == 2) { die "usage: $0 host port" } $host = $_[0]; $port = $_[1]; #creates a tcp connection to the specified host and port $handle = IO::Socket::INET->new(Proto => "tcp", PeerAddr => $host, PeerPort => $port) or die "can't connect to port $port on $host: $!"; $handle->autoflush(1); # so output gets there right away print STDERR "[Connected to $host:$port]\n"; # split the program into two processes die "can't fork: $!" unless defined($kidpid = fork()); #the if{} block runs only in the parent process if ($kidpid) { #copy the socket to standard output while (defined ($line = <$handle>)) { print STDOUT $line; } kill("TERM", $kidpid); #send SIGTERM to child } #the else{} block runs only in the child process else { # copy standard input to the socket while (defined ($line = <SCRIPT>)){ print $handle $line; } } } sub feedip { my($p); use Net::Ping; $p = new Net::Ping("icmp"); unless (@_ == 2) { die "usage: $0 host port" } if ($_[1] =~ m{\d+\.\d+\.\d+\.\d+}){ #Test to see if we +were given an IP, invalid IPs can still slip through if ($p->ping($_[1])){ #Test to see that host is up $p->close(); open(SCRIPT, $_[0]) || die "Cannot open $scrip +t\n"; # Open the script file #Fork a new process for the telnet subroutine, + wait for it to finish before returning if (!defined($telnetpid = fork())) { die "Cannot fork: $!"; } elsif ($telnetpid == 0) { telnet($_[1], 23); #Options be +ing sent t o sub telnet( IP, Port) exit; } else { waitpid($telnetpid, 0); } close(SCRIPT) || die "Cannot close $script\n"; + #Close th e script file } else{ print "$_[1] does not appear to be responding, + skipping. \n"; $p->close(); } } else { warn "$_[1] did not appear to be an IP address, skippi +ng.\n "; } }
Thanks in advance for any input you can give me.

2001-05-14 Edit by Corion : Changed title to be more descriptive. Added formatting.


In reply to Peer review of Cisco switch administration utility (was: ok I know it's crap but I'm proud of it...) by fingers

Title:
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!
  • 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
  • Outside of code tags, you may need to use entities for some characters:
            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?
    Username:
    Password:

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

    How do I use this? | Other CB clients
    Other Users?
    Others about the Monastery: (17)
    As of 2014-10-23 19:56 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      For retirement, I am banking on:










      Results (128 votes), past polls