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
Note: This is a IOS 15 feature.
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
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 R4#show shell functions #User defined functions: Function namespace: DEFAULT function test-r1() { ping 150.1.5.5 }
Reblogged this on Texas Summer Heat and commented:
After getting a chance to play with junOS late last year the ability to save past versions of configs was a huge plus. Check out how you can do the same thing on a Cisco device.
Wow, that’s amazing! I love Linux shell!
Are all of the Cisco commands still working after activating IOS.sh?
Yup IOS is still there
this is good, but the commands have very limited functionality compared to real linux commands.
in addition I have noticed a few problems
VAR1=`sh run int gi0/0.1 | grep address`
echo $VAR1
ip
it just stored the first word and not the whole sentence