Over the years I have written a few scripts to help me manage the networks I have been responsible for.  None of it is earth-shattering I am sure but I think at least some of these tools could be useful to others as well.  Not all IP/Network Engineers (router jockeys) are well versed in scripting languages and all but the smallest networks can benefit from them.  So without further adieu, here is the first of what I plan to make a series of posts on Network Tools, enjoy!

push.ksh:

I wrote push.ksh to “push” commands out to several Juniper/JUNOS routers at once.  It is a Korn shell script which leverages jlogin (an Expect script distributed with RANCID).  It can basically do one thing, two and a half ways.  It can execute the same command on a list of routers or it can run a tailored command on a list of routers.  I added the half because when running the same command on all routers, the script can pull the data from a pair of files or from the command line.  Push.ksh can be used to do many repetitive tasks across a given group of routers – including configuration changes.  This is a simple script (not unlike most of my scripts) but I have found it invaluable in many situations. The full text of the script is below, after the explanation.

Let’s first check the dependencies, found in the variables section:

#-----------Variables--------------#
#** enter the correct paths here **#
PASTE=<path>/paste_input.pl
#paste_input.pl can be found at http://odin.chrisgrundemann.com/files/scripts/perl/
JLOGIN=<path>/jlogin
#jlogin is an expect script that comes with RANCID (http://www.shrubbery.net/rancid/)
#----------------------------------#

.
As you can see, this script is dependent on two others.  We touched on jlogin above; if you have RANCID then you probably have jlogin.  Try “> whereis jlogin” to find the full path.  The second script referenced is a perl script that I adapted from some other perl scripts that my long time colleague Ryan Privette has written (full text of the script below).

Next, we take a look at the help output and basic usage:

> push.ksh --help

Chris wrote this script for personal use.
If it messes something up that is your fault for
using it in the first place.  By using this script
you agree to this.

Usage:
push.ksh -f <file with list of routers> <file with commands for every router>
push.ksh -d <directory where command files are located - named by router host name>
push.ksh -p [you then paste the list of routers and list of commands into the cli]

>

There is the disclaimer to keep co-workers from blaming me with there ill advised attempts and then the usage guide.  As you can see, there are three options which are all hopefully fairly self explanatory.  Let’s look at each in a bit more detail just in case.

 push.ksh -f <file with list of routers> <file with commands for every router>

This option should be utilized when you want to execute the exact same command on every router in a given list. Save your list of host names or IPs to act on (whatever you would use to log into the device) in one file and the list of commands to execute in another.  Push.ksh will go through the list of routers in the first file one by one and run the commands in the second file on each; displaying the entire output so that you can monitor or capture the results.

 push.sh -d <directory where command files are located - named by router host name>

This option is used when the commands must be individualized for each router.  Generate your commands and save them in files that are named with the host name (or IP) of the router in question.  Push.ksh will “ls” the directory supplied, use the contained files names as host names to (attempt to) log into and then execute the commands in that file on that router.  Again, all output is displayed.  For example:  If you want to run “show interfaces xe-1/0/0” on rtr1 and “show interfaces xe-2/1/0” on rtr2; you would create a fresh directory (mkdir) and create two files inside of it, one called rtr1 (assuming your DNS works) containing “show interface xe-1/0/0” and another named rtr2 with the line “show interface xe-2/1/0” as its contents.  Then run “> push.ksh -d <directory you created>” to have the commands executed on the respective routers.

 push.ksh -p [you then paste the list of routers and list of commands into the cli]

This final option should be used when you have a command or set of commands to execute on a list of routers but don’t want to take the time to write files beforehand.  This option works just like the first, -f, option but instead of referencing files, the lists are pasted right onto the cli.

As mentioned, all options display all output to standard out which of course means that you can monitor the action live, write it to a file or use the pipe to run other shell commands (grep is one obvious example) and better parse the data.


Here’s the text for push.ksh, just copy and paste it (CC0)!

#!/bin/ksh

#########################################################################
# WHO - Chris Grundemann                                                #
# WAT - push.ksh	                                                #
# WEN - 02-APR-08 // Last Edit: 15-May-08 (CLG)                         #
# WER - TWTC IP NOC		                                        #
# WHY - This script will push configs out to Juniper routers using	#
#     - pre-written or generated set commands 				#
#########################################################################

help () {
print '
   Chris wrote this script for personal use.
   If it messes something up that is your fault for
   using it in the first place.  By using this script
   you agree to this and further agree to kick your
   own @$$ for messing things up with a script.

Usage: push.sh -f  
       push.sh -d 
       push.sh -p [you then paste the list of routers and list of set commands into the cli]
'
}

rundir() {
# This section is utilized when the config must be individualized for
# each router.  Generate your set commands and save them in files that
# are named with the hostname (or IP) of the router in question.

for rtr in `ls -1 $RTRDIR`
 do
	echo "configure exclusive" > $HOME/temp.cmd
	cat $RTRDIR/$rtr >> $HOME/temp.cmd
	echo "show | compare" >> $HOME/temp.cmd
	echo "commit synchronize and-quit" >> $HOME/temp.cmd
	/usr/local/bin/jlogin -f $HOME/.cloginrc -x $HOME/temp.cmd $rtr
done
}

runfile() {
# This section is utilized when the config change is the same for a
# group of routers.  Save your set commands in one file and a list
# of hostnames or IPs to act on in another.

rm -f $HOME/temp.cmd

for rtr in `cat $RTRLST` 
 do
	echo "configure exclusive" > $HOME/temp.cmd
	cat $CMD >> $HOME/temp.cmd
	echo "show | compare" >> $HOME/temp.cmd
	echo "commit check" >> $HOME/temp.cmd
	echo "commit synchronize and-quit" >> $HOME/temp.cmd
	/usr/local/bin/jlogin -f $HOME/.cloginrc -x $HOME/temp.cmd $rtr
done

rm -f $HOME/temp.cmd
}

runpaste() {
# This section is utilized when the config change is the same for a
# group of routers.  With this option there is no need to create any
# files ahead of time though, you can simply paste the two lists
# onto the command line.  You must have paste_input.pl for this to
# work.

rm -f paste.cmd
rm -f paste.rtr
PASTE=/home/storage/scripts/noc/paste_input.pl

print '

Paste the list of routers to act on:'
$PASTE paste.rtr

print '

Paste the set commands to execute on all routers above:'
$PASTE paste.cmd

for rtr in `cat paste.rtr`
 do
        echo "configure exclusive" > $HOME/temp.cmd
        cat paste.cmd >> $HOME/temp.cmd
        echo "show | compare" >> $HOME/temp.cmd
        echo "commit check" >> $HOME/temp.cmd
        echo "commit synchronize and-quit" >> $HOME/temp.cmd
        /usr/local/bin/jlogin -f $HOME/.cloginrc -x $HOME/temp.cmd $rtr
done

rm -f paste.cmd
rm -f paste.rtr
}

while [ "$1" ]; do
# Here we find out how the user wants to use this tool and
# collect the needed variables.
	case "$1" in
		-d)
			RTRDIR=$2
			rundir
			exit 0
		;;
		-f)
			RTRLST=$2
			CMD=$3
			runfile
			exit 0
		;;
		-p)
			runpaste
			exit 0
		;;
		*)
			help
			exit 0
		;;
	esac
shift
done

#######
# END #
#######

And here’s the text for paste_input.pl, which is called by push.ksh (CC0):

#!/usr/bin/perl

my($save_file);
$save_file = $ARGV[0];
open (MYFILE, ">$save_file");

print "  (ctrl-d on a free line when you are done)\n";

while($line=) {
	chomp($line);
	print MYFILE "$line\n";
        }

close (MYFILE);

 

I hope this can be of use to you; if it is – please drop me a comment or an email and let me know.  Thanks!

Published On: April 7th, 2009 / Categories: Juniper, Network Tools / Tags: , , , , /

7 Comments

  1. Louis Kowolowski 23 February 2014 at 19:20 - Reply

    The link to the scripts is broken. Do you still have them?

    • Chris Grundemann 17 April 2014 at 12:55 - Reply

      I do! I’ll have to fire up an old server and recover them – thanks for the reminder! =)

  2. Matt Almgren 1 April 2015 at 22:27 - Reply

    I’m also interested in the scripts. Can you mail them to me?

    Thanks!

    • ~Chris 21 May 2015 at 12:37 - Reply

      Yeah, I just have to fire up the server all that stuff is saved on, and remember the password…

  3. ~Chris 21 May 2015 at 17:04 - Reply

    Okay guys, I just added the text directly here to avoid any future mishaps. Enjoy! Let me know how it works. No warranty or guarantee of any kind of course.

  4. WTF is SDN? ~ don't panic 16 March 2017 at 11:14 - Reply

    […] more of a continuum than a single solution. In fact, any talented network engineer who has written a script to make configuration changes, to evaluate network inventory, or to do any other network management task, has developed an SDN […]

  5. […] could gather and display some of this information in one place. And maybe you started writing some simple shell scripts to automate a bit of the tedium. As I’ve argued in the past, this is actually the beginnings of […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.