Tcl for Cisco IOS in Simple Examples
Imagine that you need to deploy dozens of Cisco access switches of the same type from scratch. A typical configuration includes a host name and a domain, a default gateway, passwords, a list of users, IP addresses for SVIs, VLAN numbers, settings for uplink trunks, etc. To enter it each time with your hands is very long and unproductive. Of course, you can create a typical config and upload it via (T) FTP, but, firstly, it will require at least minimal configuration from the console, and secondly, mutable configuration parameters still have to be changed. To solve these (as well as many other) tasks, Cisco IOS contains a powerful automation tool - a built-in Tcl interpreter (Cisco IOS scripting w / Tcl).
Tcl (readable "tickle", sometimes "flowed") is an interpreted programming language developed in the late 80s for embedding in console applications. The range of features of modern Tcl is quite wide: here there is support for OOP, and advanced regexp tools, dynamic arrays, etc.
Support for this language first appeared on the Cisco IOS 12.2 (3) T platform (in some sources it is indicated at 12.3 (2), but I did not find confirmation of this) and currently has several options:
How to determine the presence of a command interpreter knowing the device model or version of iOS? There is a Cisco Feature Navigator for this :

The Research Features menu item allows you to select a specific IOS version for a given IOS Train Release or specific hardware platform. The Research Software menu item allows you to find all versions of iOS with Tcl support for a given hardware. We click, filter the Filter by field by the name (Feature name) “Cisco IOS scripting w / Tcl” (or simply “Tcl”), add the feature name to the list, select Train release and get a list of all IOS versions containing this feature:

Unfortunately, the CFN database is incomplete and sometimes does not show all the information. So, for the CAT2960S platform, the navigator showed the presence of Tcl in the IOS 15.2E1 release and did not show in the 15.2E9 release, although in fact the Tcl interpreter is both there and there.
What can be done in Cisco IOS using Tcl? Quite a lot: browse and change the configuration, create interactive scripts, operate on MIB objects, TCP and UDP sockets, and even ... write a whole web shell!
In general, a Tcl program contains a sequence of commands separated by a newline or semicolon. Non-Explanatory Example:
Some operators:
For a more complete list see progopedia.ru/language/tcl
The Tcl interpreter starts by tclsh command from priveleged EXEC mode:
Let's execute the first script:

Exiting the interpreter is a command
Multiple Tcl interpreter sessions from different TTY sessions are allowed.
Tcl interpreter internal commands:
exec - executes the quoted command from the IOS CLI priveleged EXEC set.

produce : ios-config - executes a command from global configuration mode. Behind it, in separate pair quotes, all subsequent sub-configuration commands are indicated. For example:
equivalent to a series of iOS commands:
The Tcl interpreter prevents exec processes from interacting directly with the console. Therefore, the data are transferred to the exec processes launched from the Tcl shell using the typeahead command : First, two “y” characters will be stored in the input buffer, separated by a newline (\ n), then the reload exec command will be run, which reads from the buffer enter a cancel command or confirm a reboot and (if necessary) save the configuration. The tickle does not support typing, this must be remembered when operating with variables: The nested operator calculates the value of the expression specified in curly brackets ($ a + $ b) and performs the substitution of this value instead of square brackets. Example procedure in Tcl:

when you enter a curly brace, the interpreter will not close the command line until you enter a pair of closing braces. The procedure is stored in the interpreter memory until the end of the interpreter session with the tclquit command. This makes it possible to start procedures and access variables of previously launched scripts. Remember that an error in the script can lead to looping and blocking your (V) TTY session! The console does not have emergency shutdown facilities (such as Ctrl + Break), the only way is to start a new session and reset the “hung” session by the command
Now let's move on to solving a practical problem. Before us is the 48-port Cat2950S out of the box. The script below
Note 1. There is a small logical error in this script. Try to find her.
Note 2. Some text editors like to put an unprintable EoF character at the end of the file. It can be seen in the IOS console by listing the contents of the file with cat or more. Having stumbled upon EoF, the Tcl interpreter will throw an error and ignore the entire line. Therefore, I left an escaping comment mark at the end of the script.
The question arises: how can I write a script to the memory of a switch with an unconfigured IP, working only through the console port? Do not type the script by hand! Is it possible to manually configure the Management Interface and use FTP each time? No, it can be easier. Cisco IOS can copy files directly through the console serial port using the Xmodem protocol and save them to a flash. To do this, you need a terminal emulator with Xmodem support, for example, ZOC or Tera Term (but the popular free Putty, alas, will not work!). Copying is performed by the IOS copy xmodem: flash: filename command , after which you need to perform File Transfer in the terminal emulator menu:

This can also be done while in ROMmon (for example, if you “tear down” the switch config without a priveleged EXEC password). But copying files back (from the flash memory of the switch to the PC) is not supported.
Unfortunately, from Tcl, you cannot open a telnet session to a remote router. If you try, the
This concludes the brief excursion into the capabilities of Tcl language on the Cisco IOS platform; you can study the issue in more detail in the Cisco IOS Scripting with TCL Configuration Guide document available on the Cisco website.
What is Tcl
Tcl (readable "tickle", sometimes "flowed") is an interpreted programming language developed in the late 80s for embedding in console applications. The range of features of modern Tcl is quite wide: here there is support for OOP, and advanced regexp tools, dynamic arrays, etc.
Support for this language first appeared on the Cisco IOS 12.2 (3) T platform (in some sources it is indicated at 12.3 (2), but I did not find confirmation of this) and currently has several options:
- Tcl interpreter with command line interface. It is integrated into various versions of the Cisco IOS platform, including IOS XE and XR, and is available for a wide range of devices. Allows you to execute Tcl commands, run ready-made scripts as files, etc. Devices that use not iOS as the operating system but, for example, Cat OS or ASA (in the firewall of the same name) do not contain an interpreter command line.
- T.N. “Built-in event manager” or EEM - an event tracking system that allows you to automatically respond to them in real time. For example, monitor a remote host with an e-mail notification. EEM scripts (applets) are written in Tcl, but EEM itself does not provide a separate Tcl command line. An example of use see here . EEM is available on Nexus (NX OS) and ASA platforms from version 9.2 (1) and higher.
- Voice Menu Systems IVR (Interactive Voice Responce).
How to determine the presence of a command interpreter knowing the device model or version of iOS? There is a Cisco Feature Navigator for this :

The Research Features menu item allows you to select a specific IOS version for a given IOS Train Release or specific hardware platform. The Research Software menu item allows you to find all versions of iOS with Tcl support for a given hardware. We click, filter the Filter by field by the name (Feature name) “Cisco IOS scripting w / Tcl” (or simply “Tcl”), add the feature name to the list, select Train release and get a list of all IOS versions containing this feature:

Unfortunately, the CFN database is incomplete and sometimes does not show all the information. So, for the CAT2960S platform, the navigator showed the presence of Tcl in the IOS 15.2E1 release and did not show in the 15.2E9 release, although in fact the Tcl interpreter is both there and there.
What can be done in Cisco IOS using Tcl? Quite a lot: browse and change the configuration, create interactive scripts, operate on MIB objects, TCP and UDP sockets, and even ... write a whole web shell!
In general, a Tcl program contains a sequence of commands separated by a newline or semicolon. Non-Explanatory Example:
puts "Hello, world!"; puts "My first Tcl IOS script!"
Some operators:
#
comment to the end of the line set a 1
assignment a = 1 $a
getting the value of the variable { }
block operator - determines the body of the loop or condition [ ]
the substitution operator - when executed, the calculated value of the expression containing the == <= <>
comparison operators will be substituted for the square brackets to puts "text"
display the string "text" in stdout (i.e. i.e., to the console) puts $a
similarly for the value of the variable a, it gets stdin
reads the values from the console, set a [gets stdin]
entering the value from the console and assigning it to a variable a for {set i 1} {$i < 10} {inrc i} {....}
for loop proc {argument, ....} {body}
procedure For a more complete list see progopedia.ru/language/tcl
The Tcl interpreter starts by tclsh command from priveleged EXEC mode:
sw#Tclsh
sw(tcl)#
Let's execute the first script:

Exiting the interpreter is a command
tclquit
or just exit. Tcl is case sensitive, soPuts "Hello, world"
will cause an error, but the IOS shell command register is not important. All input commands are first processed by the Tcl interpreter, if the input command is executable with so on. Tcl, it executes and the result is output to the TTY device. If the command cannot be executed by the interpreter, it is passed to the IOS command parser. Thus, one script can combine Tcl statements and IOS commands. The IOS environment does not contain a full-fledged text editor, so pre-defined scripts must be created by external means and only then copied to flash or to memory. It also supports the precompilation of the script in bytecode with subsequent launch. The launch of the script file is executed by the commandtclsh flash:filename
Multiple Tcl interpreter sessions from different TTY sessions are allowed.
Tcl interpreter internal commands:
exec - executes the quoted command from the IOS CLI priveleged EXEC set.
sw(tcl)#exec "show int fa0"
will 
produce : ios-config - executes a command from global configuration mode. Behind it, in separate pair quotes, all subsequent sub-configuration commands are indicated. For example:
sw(tcl)#ios_config "int fa0" "ip address 192.168.0.1 255.255.255.0" "no shut"
equivalent to a series of iOS commands:
sw#conf te
sw(config)#int fa0
sw(conf-int)#ip address 192.168.0.1 255.255.255.0
sw(conf-int)#no shut
The Tcl interpreter prevents exec processes from interacting directly with the console. Therefore, the data are transferred to the exec processes launched from the Tcl shell using the typeahead command : First, two “y” characters will be stored in the input buffer, separated by a newline (\ n), then the reload exec command will be run, which reads from the buffer enter a cancel command or confirm a reboot and (if necessary) save the configuration. The tickle does not support typing, this must be remembered when operating with variables: The nested operator calculates the value of the expression specified in curly brackets ($ a + $ b) and performs the substitution of this value instead of square brackets. Example procedure in Tcl:
typeahead "y\ny"
exec "reload"

[expr {..}]
proc ping_net {x} {
for {set n 1} {$n < $x} {incr n} {
exec "ping 192.168.0.$n"
}
}
when you enter a curly brace, the interpreter will not close the command line until you enter a pair of closing braces. The procedure is stored in the interpreter memory until the end of the interpreter session with the tclquit command. This makes it possible to start procedures and access variables of previously launched scripts. Remember that an error in the script can lead to looping and blocking your (V) TTY session! The console does not have emergency shutdown facilities (such as Ctrl + Break), the only way is to start a new session and reset the “hung” session by the command
clear line
. Now let's move on to solving a practical problem. Before us is the 48-port Cat2950S out of the box. The script below
- requests from the console the serial number of the switch sw_num
- sets a hostname of the form switch_ for it
- requests and sets a password for priveleged EXEC console
- configures the address on its Fa0 control interface (192.168.0.x) and Vlan1 interface (10.0.x.254) in accordance with the entered switch number
- creates a port-based DHCP reservation and a pool of 48 addresses, in which one IP address is reserved for each client, the lower octet of which is equal to the serial number of the port through which this client is connected.
puts "Enter Switch number:"
set sw_num [gets stdin]
ios_config "hostname switch_$sw_num"
puts "Enter password (secret):"
set pass [gets stdin]
ios_config "enable secret 0 $pass"
ios_config "line 0 16" "password 0 $pass" "login"
ios_config "int fa0" "ip address 192.168.0.$sw_num 255.255.255.0" "no shut"
ios_config "int vlan1" "ip address 10.0.$sw_num.254 255.0.0.0" "no shut"
ios_config "ip dhcp use subscriber-id client-id"
ios_config "ip dhcp subscriber-id interface-name"
#перебираем в цикле все 48 портов и для каждого задаем опцию subscriber-id
for {set i 1} {$i <= 48} {incr i} {ios_config "int Gi1/0/$i" "ip dhcp server use subscriber-id client-id"}
ios_config "ip dhcp pool POOL1" "network 10.0.0.0 255.0.0.0" "reserved-only" "default-router 10.10.0.254"
# записываем в пул 48 зарезервированных IP-адресов, привязанных к соотв. порту
for {set i 1} {$i <= 48} {incr i} {ios_config "ip dhcp pool POOL1" "address 10.0.$sw_num.$i client-id Gi1/0/$i ascii"}
#
Note 1. There is a small logical error in this script. Try to find her.
Note 2. Some text editors like to put an unprintable EoF character at the end of the file. It can be seen in the IOS console by listing the contents of the file with cat or more. Having stumbled upon EoF, the Tcl interpreter will throw an error and ignore the entire line. Therefore, I left an escaping comment mark at the end of the script.
The question arises: how can I write a script to the memory of a switch with an unconfigured IP, working only through the console port? Do not type the script by hand! Is it possible to manually configure the Management Interface and use FTP each time? No, it can be easier. Cisco IOS can copy files directly through the console serial port using the Xmodem protocol and save them to a flash. To do this, you need a terminal emulator with Xmodem support, for example, ZOC or Tera Term (but the popular free Putty, alas, will not work!). Copying is performed by the IOS copy xmodem: flash: filename command , after which you need to perform File Transfer in the terminal emulator menu:

This can also be done while in ROMmon (for example, if you “tear down” the switch config without a priveleged EXEC password). But copying files back (from the flash memory of the switch to the PC) is not supported.
Unfortunately, from Tcl, you cannot open a telnet session to a remote router. If you try, the
sw(tclsh)#exec "telnet host"
session simply freezes at the stage of entering the password. This concludes the brief excursion into the capabilities of Tcl language on the Cisco IOS platform; you can study the issue in more detail in the Cisco IOS Scripting with TCL Configuration Guide document available on the Cisco website.