TCL

TCL in IOS:

  • Tool Command Language (Tcl) – interpreted programming language.
  • Tk is a library of procedures written to create graphical user interfaces (GUI) – Not available in Cisco IOS.
  • Another offshoot of Tcl is “Expect”. Expect is highly specialized to match output strings. Used for telnet,ssh,ftp.
R1#tclsh
R1(Tcl)#
  • The Tcl interpreter checks whether the entered Tcl commands are valid, and if so, the result is sent to the tty. Tcl commands that are not recognized as valid are sent to the Cisco IOS CLI parser.
  • To check the  TCL version installed on IOS:
Router(tcl)#info patchlevel
8.3.4
Router(tcl)#
  • Tcl supports only the single data type of a string.
  • To see all the variables known to a TCL interpreter use “info vars
  • To store a value to a variable use “set” command. “unset” to release the value from a variable.
  • The command “expr” evaluates the expression
  • To view a variable use “puts” command. Three channels: “stdin, stdout”, and stderr. The default channel stdout send the output to the display.
  • append” command to append or concatenate strings.” append varName value” : Append all of the value arguments to the current value of variable ‘varName’.
  • The “incr” command, without any argument, is used to increment or add 1 to an integer variable. Can perform arithmetic operation with +/- arguments.
Router(tcl)#set x 9
9
Router(tcl)#expr $x+1
10
Router(tcl)#expr $x.$x+$x
18.9
Router(tcl)#expr $x.$x
9.9
Router(tcl)#expr $x*$x
81
Router(tcl)#puts $x
9
Router(tcl)#puts $x*$x
9*9
Router(tcl)#set x "this is x"
this is x
Router(tcl)#set y "this is y"
this is y
Router(tcl)#puts $x$y
this is xthis is y
Router(tcl)#append x $y
this is xthis is y
Router(tcl)#puts $x
this is xthis is y
Router(tcl)#set z 3
3
Router(tcl)#incr z +1
4
Router(tcl)#puts $z
4
Router(tcl)#unset z
Router(tcl)#puts $z
can't read "z": no such variable
Router(tcl)#set z(1) 1
1
Router(tcl)#set z(x) 100
100
Router(tcl)#set {This is a long "#!@%" var} 10
10
#{} : Strings are taken as it is..
Router(tcl)#set number 10
10
Router(tcl)#puts {example for curly braces $number}
example for curly braces $number

 
  • List: Collection of values separated by white space.
Router(tcl)#set counters "1 2 3 4 5"
1 2 3 4 5
Router(tcl)#puts $counters
1 2 3 4 5
  • lappend to add a value to a list:
Router(tcl)#lappend counters 6
1 2 3 4 5 6
Router(tcl)#puts $counters
1 2 3 4 5 6
  • lindex to provide the values stored in the list at an index value. First value is index#0
Router(tcl)#lindex $counters 4
5
  • linsert to insert a value at an index location. “linsert <index> <value>”
Router(tcl)#linsert $counters 0 1
1 1 2 3 4 5 6
Router(tcl)#puts $counters
1 2 3 4 5 6
Router(tcl)#set counters [linsert $counters 0 0]
0 1 2 3 4 5 6
Router(tcl)#puts $counters
0 1 2 3 4 5 6
Router(tcl)#llength counters
1
Router(tcl)#llength $counters
7
  • “lsearch $list_name {<index#> | -regex | -exact | – glob }. lsearch searches for the index number if a match is found or returns -1 if no match. glob: patterns containing ‘*’ (wildcard) and ‘?’ (joker).
Router(tcl)#lsearch $counters 5
5 << output 5 is value on the 5th index
Router(tcl)#lsearch $counters 7
-1
Router(tcl)#
  • “lreplace $list_name <starting index> <ending index>  <replace value>”
Router(tcl)#puts $counters
0 1 2 3 4 5 6
Router(tcl)#set counters [lreplace $counters 3 5 replaced]
0 1 2 replaced 6
Router(tcl)#puts $counters
0 1 2 replaced 6
Router(tcl)#llength $counters
5
Router(tcl)#lrange $counters 1 3
1 2 replaced
Router(tcl)#puts $counters
1 2 3 4 5
Router(tcl)#lsort -decreasing $counters
5 4 3 2 1
  • Procedure: Call function. Syntax: “proc name args body
    • for” function to emulate loop. Same as in C programming.Syntax: “”for start test next body”
    • foreach” to emulate loop with a list of variables. “foreach varList list command”
    • while” same as in C programming. “while test command”
  • Loop program:
Router(tcl)#proc test1 {} { set z 123
Router(tcl)#puts $z }
Router(tcl)#test1
123
Router(tcl)#
Router(tcl)#for { set e 1} {$e<10} {incr e -1} { test1 }
123
123
123
123
123
123
…. <control+6 to break the loop>
  • Example for  foreach:
set temp "r1 35 r2 60 r3 40"
foreach {router t1} $temp {
puts "Module 1 temperature of $router is $t1"
}

Output:

Module 1 temperature of r1 is 35
Module 1 temperature of r2 is 60
Module 1 temperature of r3 is 40
  • Example for while:
Router(tcl)#
Router(tcl)#set y 0
0
Router(tcl)#while {$y<3} {
Router(tcl)#puts "Value of y is $y"
Router(tcl)#incr y
Router(tcl)#}
Value of y is 0
Value of y is 1
Value of y is 2
  • Arrays are a structured collection of variables. Array command syntax: “array {option} arrayName”
Router(tcl)#set cpuval(r1) {25 30 20}
25 30 20
Router(tcl)#set cpuval(r2) {10 5 7}
10 5 7
Router(tcl)#set cpuval(r3) {40 50 38}
40 50 38
Router(tcl)#
Router(tcl)#array get cpuval
r2 {10 5 7} r3 {40 50 38} r1 {25 30 20}
Router(tcl)#array get cpuval r3
r3 {40 50 38}
Router(tcl)#
Router(tcl)#array size cpuval
3
Router(tcl)#
Router(tcl)#array startsearch cpuval
s-1-cpuval <<< token is generated.
Router(tcl)#array anymore cpuval s-1-cpuval
1
Router(tcl)#array nextelement cpuval s-1-cpuval
r2
Router(tcl)#array nextelement cpuval s-1-cpuval
r3
Router(tcl)#array nextelement cpuval s-1-cpuval
r1
Router(tcl)#array anymore cpuval s-1-cpuval
0
Router(tcl)#array nextelement cpuval s-1-cpuval
Router(tcl)#
Router(tcl)#array donesearch cpuval s-1-cpuval
Router(tcl)#array get cpuval
r2 {10 5 7} r3 {40 50 38} r1 {25 30 20}
Router(tcl)#array names cpuval
r2 r3 r1
Router(tcl)#array unset cpuval r3
Router(tcl)#array get cpuval
r2 {10 5 7} r1 {25 30 20}
Router(tcl)#array names cpuval
r2 r1
Router(tcl)#
  • “if” statement used as in C programming.
Router(tcl)#set t [array size cpuval]
2
Router(tcl)#
if {$t==3} {
puts "size of array is 3" } else {
puts "someone changed array" }
  • “switch” case statement. If no match is found, no string is returned. Always recommended to have “default”.  No “break” statement is needed. If there is match, the switch operation ends.
% set t 100
100
% puts $t
100
% switch $t {
"100" { puts "t=100"}
default { puts "t!=100"}
}
t=100
%
% set t 200
200
% switch $t {
"100" { puts "t=100"}
default { puts "t!=100"}
}
t!=100
%

File Handling:

  • Declare a variable to open a file. Make sure to ‘close’ that variable after use to avoid wastage of resources. The variable is a pointer to the contents in the file.
#variable 'var1' is created to handle a file 'file1' with read-only permission.
Router(tcl)#set var1 [open file1 r]
file0
##gets provide the output of value stored by the variable. It can be saved to a new variable too. like ##"gets $var1 var2". Current value pointed by the var1 is stored in var2.
## The pointer keeps incrementing when we use the 'gets' command.
Router(tcl)#gets $var1 
Building configuration...
Router(tcl)#puts $var1
file0
Router(tcl)#gets $var1
 
Router(tcl)#gets $var1
Current configuration : 4062 bytes
Router(tcl)#gets $var1
!
## we can see the current location pointed by the variable using 'tell' command.
Router(tcl)#tell $var1
64
Router(tcl)#gets $var1
upgrade fpd auto
Router(tcl)#tell $var1
81
Router(tcl)#
## read next 10 characters pointed by current 'var1'
Router(tcl)#read $var1 10
service co
Router(tcl)#
Router(tcl)#gets $var1
unters max age 5
Router(tcl)#
 
##The file pointer can be moved to any location using the 'seek' command.
Router(tcl)#seek $var1 0
## Pointer moved to beginning of the file.
Router(tcl)#gets $var1
Building configuration...
Router(tcl)#
## after all operations, close the pointer variable.
Router(tcl)#close $var1
  • To check whether tcl is installed in IOS use “show subsys name tcl’ command.
  • Provide an arbitrary word to check the available options under a command.
Router(tcl)#info dontknow
bad option "dontknow": must be args, body, cmdcount, commands, complete, default, exists, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars
Router(tcl)#
  • To pass a command directly to the IOS command processor while in the Tcl shell, enter the command in quotes after the Tcl exec command.
  • To save the output of IOS command, using “set variable1 [exec “show run”]”
  • To suppress the output of the command results use “log_user 0” command. Toggle to undo.
  • “string bytelength $var2” to check the size of output stored in the variable.
  • “string toupper $var2” to change the output to all upper case. Output can be saved to another variable using “set var3 [string toupper $var2]”
  • To search a string use “string first” command. Returns byte count number if there is any hit else -1.
  • “string first “string1″ $variable”  : To search for the “string1” in the variable.
  • “string length ‘string1’ “ : To provide the length of string1
  • “string range $file $beginning $end”:  Provides the string in the file from ‘beginning’ to ‘end’.
Router(tcl)#set var2 [exec "show ip route"]
<snip>
 10.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
S 10.0.0.0/8 is directly connected, GigabitEthernet2/48
C 10.16.151.0/24 is directly connected, GigabitEthernet2/48
Router(tcl)#
Router(tcl)#string first "12.1.1." $var2
-1
Router(tcl)#string first "10.16.151" $var2
651
Router(tcl)#
  • TCL scripts can be stored in flash and can be invoked by the TCL interpreter using “source” command. “Source flash:filename.tcl”  << when in TCL mode
  • “tclsh flash:filename.tcl <arguments>”   <<  the script will run and exit the interpreter.
  •  ios_config  ‘command’   : To execute config mode commands from TCL mode.
  • Snmp_getone ‘community’ ‘oid’  to get the snmp get.
  • Snmp_getnext ‘community’ ‘oid’  to get the snmp next.
  • Snmp_setany ‘community_rw’ ‘oid’ ‘input_type’ ‘input_value’ to change configuration via snmp.
Router(tcl)#ios_config "clock timezone te 4" "end"
Router(tcl)#
Router(tcl)#snmp_getone public ifOperStatus.52 
{<obj oid='ifOperStatus.52' val='1'/>} <<< xml coding output.
Router(tcl)#
Router(tcl)#snmp_getone public ifOperStatus.51 << use "show snmp mib ifmib ifindex gi " to get index.
{<obj oid='ifOperStatus.51' val='2'/>}
Router(tcl)#snmp_getnext public ifOperStatus.51
{<obj oid='ifOperStatus.52' val='1'/>}
Router(tcl)#snmp_getbulk public 0 3 ifOperStatus.1
{<obj oid='ifOperStatus.2' val='2'/>}
{<obj oid='ifOperStatus.3' val='2'/>}
{<obj oid='ifOperStatus.4' val='2'/>}
Router(tcl)#
  • “typeahead” command is used to enter ‘yes’ or ‘no’ to commands which requires user confirmation. (like clear arp/clear interface etc).

References:

http://www.cisco.com/en/US/docs/ios/12_3t/12_3t2/feature/guide/gt_tcl.html

http://wiki.nil.com/Tclsh_on_Cisco_IOS_tutorial

http://www.packetlevel.ch/html/cisco/tcl.html

TCL Scripting for Cisco IOS.

Advertisements
This entry was posted in IOS, Scripting and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s