Using clogin to automate some boring stuff

In some cases we need do some boring stuff, for example, checking every devices to document hardware type, serier number; to backup configuraiton; doing the same tiny changes on each network devices. It is time-consuming too if you have massive similar devices that you have to login and check one by one. This type of works can be automated by using clogin plus some simple scripts.

According to the maual,  clogin is an expect(1) script to automate the process of logging into a Cisco router, Catalyst switch, Extreme switch, Juniper ERX/E-series, Procket Networks, or Redback router. There are complementary scripts for Alteon, Avocent (Cyclades), Bay Networks (nortel), ADC-kentrox EZ-T3 mux, Foundry, HP Procurve switches and Cisco AGMs, Hitachi routers, Juniper Networks, MRV optical switch, Mikrotik routers, Netscreen firewalls, Netscaler, Riverstone, Netopia, Cisco WLCs and Xirrus arrays.

clogin reads the .cloginrc file for its configuration, then connects and logs into each of the routers specified on the command line in the order listed. Command-line options exist to override some of the directives found in the .cloginrc configuration file.

Below are simple examples of how clogin works:

Example 1

We want to login to each devices and check its serier number.  Let us assume that we have 20 devices, all of them are Juniper EX switches. Indead of logining and checking every devices, we can do the following script in Linux:

  1. list all devices hostname into a file “switches”
  2.  run the following script: for i in `cat /tmp/switches`; do /local/rancid/bin/clogin -autoenable -c “show virtual-chassis” $i >> /tmp/switchessn; done
  3. trim “switchessn” file to remove noneed text if necessary. now we have a file that contain all serier number and hardware type of switches

Example 2

If we need find our root bridge for each vlans in a layer 2 networks. Below is the script that I learned:

  1. Run the the first step to get the bridge ID´s of all the switches listed int eh file swtiches.txt
    for i in `cat /tmp/switches.txt`; do /local/rancid/bin/clogin -autoenable -c "sh spanning-tree bridge \n\n end" $i > /tmp/$i; done
  2. Purge the documents from step 1 to only contan the isolated bridge-id for each switch
    for b in `cat /tmp/switches.txt`; do egrep -o -m 1 "[[:space:]][[:alnum:]]{1,4}\.[[:alnum:]]{1,4}\.[[:alnum:]]{1,4}[[:space:]]" /tmp/170390/$b > /tmp/access-bridge-id/bridge-id_$b.txt; done
  3. As step 3 to collect the “spanning-tree root-id” table from each swith in the switches.txt document
    for v in `cat /tmp/switches.txt`; do /local/rancid/bin/clogin -autoenable -c "sh spanning-tree root \n\n end" $v > /tmp/root-id/root-id_$v; done
  4. Collect all file names containing the access-switch bridge-id´s to one file for parsing during the last step:
    printf "%b\n" /tmp/170390/access-bridge-id/* > /tmp/170390/access-bridge-id/access-bridges.txt
  5. Finally extract all the entries from the previous steps to find out what VLAN´s each access-switch is root bridge for.
    for x in `cat /tmp/170390/access-bridge-id/access-bridges.txt`; do grep -f $x /tmp/170390/root-id/* >> /tmp/170390/final/final.txt ; done

String Manipulation

refer to linux foundation course from edx:

Operator Meaning
[[ string1 > string2 ]] Compares the sorting order of string1 and string2.
[[ string1 == string2 ]] Compares the characters in string1 with the characters in string2.
myLen1=${#string1} Saves the length of string1 in the variable myLen1.

At times, you may not need to compare or use an entire string. To extract the first character of a string we can specify:
${string:0:1} Here 0 is the offset in the string (i.e., which character to begin from) where the extraction needs to start and 1 is the number of characters to be extracted.
To extract all characters in a string after a dot (.), use the following expression: ${string#*.}

to check if a file exists, use the following conditional test:
[ -e <filename> ]
to check if a directory exists, use the following conditional test:
[ -d <filename> ]
to check if a sym-link exists, use the following conditional test:
[ -s <sym-link> ]


useful bash expressions

Use man bash to check the description of the following experssions:
$ Expands to the process ID of the shell. In a () subshell, it expands to the process ID of the current shell, not the subshell.
# Expands to the number of positional parameters in decimal
? Expands to the status of the most recently executed foreground pipeline
$# the number of parameters with which the script has been called
$? reads the exit status of the last command executed, $? == 0 if all commands exit successfully.After a function returns, $? gives the exit status of the last command executed in the function.
&& Logical AND
lets you do something based on whether the previous command completed successfull.More precisely, && will evaluate the second expression iff the first expression returns 0
exit command terminates a script, just as in a C program. It can also return a value, which is available to the script’s parent process.
exit 0 Every command returns an exit status (sometimes referred to as a return status or exit code). A successful command returns a 0, while an unsuccessful one returns a non-zero value that usually can be interpreted as an error code. Well-behaved UNIX commands, programs, and utilities return a 0 exit code upon successful completion, though there are some exceptions.

&> Bash allows both the standard output (file descriptor 1) and the standard error output
(file descriptor 2) to be redirected to the file whose name is the expansion of word
with this construct.
There are two formats for redirecting standard output and standard error:
Of the two forms, the first is preferred.
&> /dev/null send standard output to blackhole

&> /dev/null send standard output to blackhole
>/dev/null 2>&1
There are always three default files open. stdin (0) stdout (1) stderr (2)
2>&1 is asking to direct all the STDERR as STDOUT, (ie. to treat all the error messages generated from the script as its standard output). Now we already have > /dev/null at the end of the script which means all the standard output (STDOUT) will be written to /dev/null. Since STDERR is now going to STDOUT (because of 2>&1) both STDERR and STDOUT ends up in the blackhole /dev/null. In other words, the script is silenced.

$0 The filename of the current script.
$n These variables correspond to the arguments with which a script was invoked. Here n is a positive decimal number corresponding to the position of an argument (the first argument is $1, the second argument is $2, and so on).
$* All the arguments are double quoted. If a script receives two arguments, $* is equivalent to $1 $2.
$@ All the arguments are individually double quoted. If a script receives two arguments, $@ is equivalent to $1 $2.
$? The exit status of the last command executed.
$$ The process number of the current shell. For shell scripts, this is the process ID under which they are executing.
$! The process number of the last background command.