Tclsh basics

To enter the Tcl shell in the router, when in privileged EXEC mode, type tclsh.
Then type info patchlevel to find out what version of Tcl the router is using, to leave the Tcl shell use tclquit or exit.

Within the Tcl shell you can get information with the info command including the router hostname using info hostname. The typeahead command can be used to automate response to action confirmations, typeahead "reload\n\y\n\n\n"

    Router#tclsh
    Router(tcl)#
    Router(tcl)#info patchlevel
    8.3.4
    Router(tcl)#
    Router(tcl)#tclquit
    Router#
    Router#tclsh
    Router(tcl)#
    Router(tcl)#typeahead "reload\n\y\n\n\n" 

The ios_config command allows for modification of the router configuration, log_user 0|1 disables|enables the command output under configuration mode, and normal show commands can be ran by exec "show interfaces".

Tcl procedures

Tcl code can be pasted directly into the routers Tcl shell for short commands, if the code is wrapped into a procedure it can be called repeatedly with the procedure name so long as the Tcl shell is not exited. To find out what procedures are loaded and available use the info proc command, to see the code of a procedure use info body [procName]
Procedures must be called with the same number of arguments as defined by the procedure, proc snmpGetOne {oidList} in this case a list of OID's.
However by using the word args as the last procedure definition argument any number of further arguments can be passed to the procedure and they will be available via the list $args within the procedure.

Router(tcl)#proc test {rollCall args} {
+>puts "rollCall: $rollCall"
+>puts "args: $args"
puts "Number of args: [llength $args]"
+>}
Router(tcl)#test {Pugh, Pugh, "Barney McGrew",} Cuthbert, Dibble and Grub
rollCall: Pugh, Pugh, "Barney McGrew",
args: Cuthbert, Dibble and Grub
Number of args: 4
Router(tcl)#

Tcl script files

Tcl scripts in files can be ran from the privileged EXEC prompt with tclsh [location][filename.tcl] or from within the Tcl shell with source [location][filename.tcl], the file can be stored locally on the router or accessed via FTP/TFTP/HTTP..

A Tcl file can also be automatically loaded whenever the Tcl shell is entered allowing frequently used procedures to be readily available by setting within the global configuration mode,

scripting tcl init [location][filename.tcl]

When a Tcl script is called a list of arguments can be passed into the script by adding them after the script filename,

tclsh [location/filename] var1 var2 var.....

They are available within the script as a list via $argv,
$argc is the number of items in the list $argv,
$arg0 is the location and name of the script called.

Aliases can be setup in the global configuration to initialise the Tcl shell, call a Tcl script and pass a list of arguments to the script.

alias exec [name] tclsh [Tcl script] [list of arguments]

Tclsh SNMP access

The MIB's and OID's can be looked up at cisco.com, there is easy access to SNMP objects using,


snmp_getid, snmp_getone, snmp_getnext, snmp_setany, snmp_getbulk.

An snmp-server community string needs to be set up in the global configuration mode to permit access to SNMP,

snmp-server community [string] [ro|rw|...] [number of access list (optional)].
snmp-server community tcl ro

Running snmp_getone commands from the Tcl shell directly via their OID and object names,


Router(tcl)##Get the ADSL downstream sync rate.
Router(tcl)#snmp_getone tcl 1.3.6.1.2.1.10.94.1.1.2.1.8.9 adslAtucCurrAttainableRate.9
(<obj oid='adslAtucCurrAttainableRate.9' val='7692000'/>)
(<obj oid='adslAtucCurrAttainableRate.9' val='7692000'/>)
Router(tcl)#
Router(tcl)##Get the router uptime, in TimeTicks.
Router(tcl)#snmp_getone tcl 1.3.6.1.2.1.1.3.0 sysUpTime.0
{<obj oid='sysUpTime.0' val='717132'/>}
Router(tcl)#
Router(tcl)##Get the 'snmp-server location' value, if set in the config.
Router(tcl)#snmp_getone tcl 1.3.6.1.2.1.1.6.0 system.6.0 
{<obj oid='system.6.0' val='The Fire Station'/>}
Router(tcl)#
Router(tcl)##Get the router fq Domain name.
Router(tcl)#snmp_getone tcl 1.3.6.1.2.1.1.5.0 system.5.0
{<obj oid='system.5.0' val='Router.trumpton.gb.com'/>}
Router(tcl)#

Putting this into a procedure to fetch one or more OID's as a list, this can be pasted directly into the Tcl shell. Ensure you have an snmp community string setup for Tcl, or change the code to match your own string.


  1. proc snmpGetOne {oidList} {
  2. set communityStr tcl
  3. foreach oid $oidList {
  4. set snmpResult [snmp_getone $communityStr $oid]
  5. if [string match "*snmp error*" $snmpResult] {
  6. regexp {text='(.*)'} $snmpResult regexAll bRefValue
  7. lappend oidResult "Error: $bRefValue"
  8. } elseif [string match "*NO_SUCH_I*" $snmpResult] {
  9. regexp {val='(.*)'} $snmpResult regexExp bRefVal
  10. lappend oidResult "Error: $bRefVal"
  11. } else {
  12. regexp {val='(.*)'} $snmpResult regexExp bRefVal
  13. lappend oidResult $bRefVal
  14. }
  15. }
  16. return $oidResult
  17. }
  18. snmpGetOne {1.3.6.1.2.1.1.5.0 1.3.6.1.2.1.1.6.0 1.3.6.1.2.1.1.3.0}

If the previous procedure snmpGetOne was stored in a file snmpGetOne.tcl located on the router flash drive within folder tcl it would be called with tclsh flash:/tcl/snmpGetOne.tcl, note the file does not actually need to be saved with the .tcl part.

Configure an alias exec shortcut for a TCL script.

The below script can then be ran manually with the following command:

tclsh flash:/tcl/snmpGetOne.tcl 1.3.6.1.2.1.1.5.0 1.3.6.1.2.1.1.6.0 1.3.6.1.2.1.1.3.0

Or better still setup as an alias command for quicker execution of the procedure,

alias exec snmpG tclsh flash:/tcl/snmpGetOne.tcl

and called with snmpG [OIDlist], eg snmpG 1.3.6.1.2.1.1.5.0 1.3.6.1.2.1.1.3.0


  1. proc snmpGetOne {oidList} {
  2. set communityStr tcl
  3. foreach oid $oidList {
  4. set snmpResult [snmp_getone $communityStr $oid]
  5. if [string match "*snmp error*" $snmpResult] {
  6. regexp {text='(.*)'} $snmpResult regexAll bRefValue
  7. lappend oidResult "Error: $bRefValue"
  8. } elseif [string match "*NO_SUCH_I*" $snmpResult] {
  9. regexp {val='(.*)'} $snmpResult regexExp bRefVal
  10. lappend oidResult "Error: $bRefVal"
  11. } else {
  12. regexp {val='(.*)'} $snmpResult regexExp bRefVal
  13. lappend oidResult $bRefVal
  14. }
  15. }
  16. return $oidResult
  17. }
  18. #snmpGetOne {1.3.6.1.2.1.1.5.0 1.3.6.1.2.1.1.6.0 1.3.6.1.2.1.1.3.0}
  19. if { $argc == 0 } {
  20. puts "Script snmpGetOne.tcl requires at least one OID variable"
  21. puts "eg, snmpGetOne.tcl 1.3.6.1.2.1.1.5.0 1.3.6.1.2.1.1.6.0 1.3.6.1.2.1.1.3.0"
  22. } else {
  23. puts [snmpGetOne $argv]
  24. }

Tcl scripts ran from the Tcl shell do not have access to any local variable storage in memory, variables you want to pass between tclsh shell sessions needs to be saved to file on the flash or better still a USB stick, or even sent/retrieved over the network via HTTP,ftp,TFTP ect.
Go to the next page to have a look at EEM Policies written in Tcl, which have access to local variable storage and as well as other advantages.