Today we’re going to go over a little known shell in IOS that gives us some bash like functionality! It is called IOS.sh
We can enable this little known functionality with the terminal shell command, like the rest of the terminal commands this only enables IOS.sh for the current terminal session.
R1#terminal shell
If you want to have the shell enabled permanently with the following global command
R1(config)#shell processing full
R1#show terminal | in Shell
Shell: enabled
Shell trace: off
Now IOS.sh is enabled! Awesome! But what does it do?
The simple answer is it makes IOS more like a Linux shell, it allows us to create variables, make loops, and use some linux utilities like grep or wc on the shell.
Using GREP
One of the neatest features of IOS.sh is the ability to use the grep utility to filter output. Let’s start by looking at the manpage for Grep, yes there are manpages!
R1#man grep
NAME
grep - get regular expression
SYNOPSIS
grep [OPTIONS] <Regular Expression> [<file>...]
DESCRIPTION
The 'grep' command matches lines in the given files
with the supplied regular expression, and prints matching
lines. There are lots of options
-b - match everything in a file after pattern
-c - print a count of lines instead of matched lines
-e <pat> - use <pat> as the pattern (it may have a leading minus)
-h - do not print filename for each match (default)
-H - print filename for each match
-i - ignore case
-l - print only files with match
-L - print only files without match
-m - match everything in a matching mode
-n - print line numbers along with matches
-q - quiet, only set status
-s - supress printing errors
-u - match everything in a file until pattern
-v - invert match, print non-matching lines
Part of the power of this command is because you can be more flexible than the standard include pipe command because you can do things like combine include and exclude like statements in the same line.
R1#show ip route | grep (150) | grep (10003)
O 150.1.2.2 [110/10003] via 155.1.146.4, 15:51:41, GigabitEthernet1.146
O 150.1.3.3 [110/10003] via 155.1.146.4, 15:51:41, GigabitEthernet1.146
O IA 150.1.22.22 [110/10003] via 155.1.146.4, 1d11h, GigabitEthernet1.146
R1#show ip route | grep (150) | grep -v (10003)
150.1.0.0/32 is subnetted, 11 subnets
C 150.1.1.1 is directly connected, Loopback0
O 150.1.4.4 [110/2] via 155.1.146.4, 15:51:57, GigabitEthernet1.146
O 150.1.5.5 [110/3] via 155.1.146.4, 15:51:57, GigabitEthernet1.146
O 150.1.6.6 [110/2] via 155.1.146.6, 1d12h, GigabitEthernet1.146
O IA 150.1.7.7 [110/3] via 155.1.146.6, 1d12h, GigabitEthernet1.146
O IA 150.1.8.8 [110/4] via 155.1.146.4, 15:52:07, GigabitEthernet1.146
O IA 150.1.9.9 [110/4] via 155.1.146.6, 1d12h, GigabitEthernet1.146
O IA 150.1.10.10 [110/5] via 155.1.146.4, 15:52:07, GigabitEthernet1.146
R1#show ip route | grep 150 | grep -v 10003 | grep 6\.6
O 150.1.6.6 [110/2] via 155.1.146.6, 00:35:18, GigabitEthernet1.146
O IA 150.1.7.7 [110/3] via 155.1.146.6, 00:35:08, GigabitEthernet1.146
O IA 150.1.9.9 [110/4] via 155.1.146.6, 00:35:08, GigabitEthernet1.146
WC
WC can be used to count the number of things in the output.
R1#man wc
NAME
wc
SYNOPSIS
wc [OPTION]... [FILE]...
DESCRIPTION
Print newline, word, and byte counts for each FILE, and a total line if
more than one FILE is specified. Read pipe input if no files are given
-c print the byte counts
-m print the character counts
-l print the newline counts
-L print the length of the longest line
-w print the word counts
R1#show run | wc -l
216
Heads and Tails
These commands can be used to show the top x or bottom x lines of output, this can be handy with trying to see the latest logs.
R1#man head
NAME
head - print the first lines in the input
SYNOPSIS
head [<n>]
DESCRIPTION
The 'head' program will print the first lines in
its input. If given a numeric argument, it will
print that many lines. The default number of lines
is 10.
R1#man tail
NAME
tail - print the last lines in the input
SYNOPSIS
tail [<n>]
DESCRIPTION
The 'tail' program will print the last lines
in its input. If given a numeric argument, it
will print that many lines. The default number
of lines is 10.
R1#
R1#show run | head 10
Building configuration...
Current configuration : 2844 bytes
!
! Last configuration change at 18:14:38 UTC Tue Nov 17 2015
!
version 15.5
no service timestamps debug uptime
no service timestamps log uptime
no platform punt-keepalive disable-kernel-core
R1#show run | tail 10
exec-timeout 0 0
privilege level 15
logging synchronous
stopbits 1
line vty 0 4
privilege level 15
no login
!
!
end
CAT
Ok fine, we can use the cat command to view text files on the Cisco device.
R1#man cat
NAME
cat - write files or standard input to output
SYNOPSIS
cat [<file>...]
DESCRIPTION
The cat command writes whatever it sees to its output
R1#copy running-config flash:cat.test
Destination filename [cat.test]?
2844 bytes copied in 0.463 secs (6143 bytes/sec)
R1#cat flash:cat.test
!
! Last configuration change at 18:14:38 UTC Tue Nov 17 2015
!
version 15.5
no service timestamps debug uptime
no service timestamps log uptime
no platform punt-keepalive disable-kernel-core
platform console serial
Variables
Lets start with making variables by first looking at the variables
R1#man variables
NAME
variables - describe the usage of variables
DESCRIPTION
Variables can be used in any context except single quotes. Variables
can either be named, or numbered parameters to functions. Setting a
named variable can be accomplished using an assignment statement.
Assignment statments have a specific form, which is that the name of
the variable must be immediately followed by an '=' sign. There can be
no whitespace between the name and the '=':
router> MYVAR='abc'
The right side of the assignment is any string, but can also be the
result of execution of a backquote expression, or the evaluation of a
variable expansion.
Variables may be used anywhere in subsequent input lines. One could,
for example, create a shortcut for an interface name, and use it in
config mode, or create a variable containing a number, and increment
its value using arithmetic expression syntax (see man expressions).
The main issue here is that the variable introduction character may
conflict with existing usages, and so must be escaped in situations
where a compatibility issue may arise. Please see man compatibility
for more information.
To make a variable you simply have to enter VariableName=VariableValue
R1#VAR1=Value1
R1#VAR2=Value2
We can view the contents with the echo command
R1#echo $VAR1 $VAR2
Value1 Value2
You can also use variables in your commands
R2#var1=150.1.4.4
R2#ping $var1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.4.4, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 71/100/167 ms
Conditions and Loops
Following comparison operators can be used for working with integer values:
Operators Characteristics
-eq ==
-ne !=
-lt <
-gt >
-ge >=
-le =<
For working with files following conditions are available:
Operator Characteristics
-a or –e True if file exists
-d True if file exist and it is a directory
-f True if file exists and is a regular file
-r True if file exists and is readable
-s True if file exists and has a size greater than zero
-w True if file exists and is executable
-nt Test if file1 is newer than file2. The modification date on the file is used for this comparison
-ot Test if file1 is older than file2
Loops are very powerful (and dangerous if you don’t terminate them correctly) tools that allow you to carry out complex tasks.
R1#for x in 1 2 3 4 5 6 7 8 9
do..done>do
do..done>;ping 150.1.$x.$x
do..done>done
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.1.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 5/13/39 ms
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.2.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 64/140/228 ms
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.3.3, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 52/91/186 ms
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.4.4, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 31/61/117 ms
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.5.5, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 42/73/117 ms
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.6.6, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 34/51/93 ms
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.7.7, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 53/73/97 ms
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.8.8, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 67/98/116 ms
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.9.9, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 78/98/122 ms
Functions
Lastly for this blog entry, you can define functions to make repeated tasks easier.
R1#function test-r1() {
{..} >ping 150.1.4.4
{..} >}
R1#
R4#test-r1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 150.1.5.5, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 26/39/63 ms
You can see the functions defined on the system with show shell function
User defined functions:
Function namespace: DEFAULT
R1#function test-r1()
{
ping 150.1.5.5
}
Taken From: