Imagine that you need to deploy from scratch a dozen of similar Cisco access switches. Typical configurations include hostname and domain name, default gateway, passwords, user list, IP addresses for SVI, VLAN numbers, uplink trunk settings, etc. To enter it every time with hands is very long and unproductive. Of course, you can create a typical config and upload it via (T) FTP, but, first, it will require at least the minimum configuration from the console, and secondly, the configuration parameters that are changed will still have to be changed. To solve such (and many other) tasks, Cisco IOS contains a powerful automation tool — the built-in Tcl interpreter (Cisco IOS scripting w / Tcl).
What is Tcl
Tcl (read “tickle”, sometimes “flowed”) is an interpreted programming language developed in the late 80s for embedding into console applications. The range of capabilities of modern Tcl is quite wide: here it supports OOP, developed 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 command line interpreter. Built 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 run Tcl commands, run pre-made scripts as files, etc. Devices that use not the IOS as the operating system, for example, Cat OS or ASA (in the same firewall), do not contain an interpreter command line.
- T.N. “Embedded event manager” or EEM is 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 to Tcl, but EEM itself does not provide a separate Tcl command line. Example of use, see here . EEM is available on the Nexus platform (NX OS) and ASA from version 9.2 (1) and above.
- Voice menu systems IVR (Interactive Voice Responce).
How to determine the presence of the command interpreter knowing the device model or version of IOS? There is
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 a specific hardware platform. The
Research Software menu item allows you to find all IOS versions with Tcl support for a given hardware. Click, filter the Filter by field by name (Feature name) “Cisco IOS scripting w / Tcl” (or simply “Tcl”), add the name of the feature 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.
So what can I do in Cisco IOS using Tcl? Quite a lot: view and change configuration, create interactive scripts, operate with 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. Example not requiring explanation:
puts "Hello, world!"; puts "My first Tcl IOS script!"
Some operators:
#
comment to end of line
set a 1
assignment a = 1
$a
get the value of a variable
{ }
block operator - defines the body of the cycle or conditions
[ ]
substitution statement - when executed, instead of square brackets, the calculated value of the expression they contain will be substituted
== <= <>
comparison operators
puts "text"
displays the string "text" on stdout (i.e., on the console)
puts $a
same for variable a
gets stdin
reads values ​​from console
set a [gets stdin]
enter a value from the console and assign it to the variable a
for {set i 1} {$i < 10} {inrc i} {....}
for loop
proc {argument, ....} {body}
procedure
For a complete list, see
progopedia.ru/language/tclThe Tcl interpreter is started by the tclsh command from the priveleged EXEC mode:
sw#Tclsh sw(tcl)#
Run the first script:

The output from the interpreter is the
tclquit
command or just exit. Tcl is case sensitive, so
Puts "Hello, world"
will cause an error, but the IOS shell command register is unimportant. All commands entered are first processed by the Tcl interpreter, if the command entered is executable from that. Tcl, it is executed and the result is output to a TTY device. If the command cannot be executed by the interpreter, it is passed to the IOS command parser. Thus, a single script can combine Tcl statements and IOS commands. The IOS environment does not contain a full-fledged text editor, therefore, pre-defined scripts need to be created by external means and only then copied to flash or to memory. It also supports precompiling the script into bytecode and then launching it. Running a file with a script for execution is performed by the command
tclsh flash:filename
Multiple Tcl interpreter sessions from different TTY sessions are allowed.
Tcl interpreter internal commands:
exec - executes the command in quotes from the IOS CLI set priveleged EXEC.
sw(tcl)#exec "show int fa0"
will display:
ios-config - executes a command from global configuration mode. Behind it, all subsequent sub-configuration commands are specified in separate double quotes. 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 directly interacting with the console. Therefore, data transfer to exec processes running from the Tcl shell is done using the
typeahead command :
typeahead "y\ny"
exec "reload"
First, two “y” characters will be saved in the input buffer, separated by a line break (\ n), then the exload reload command will be run, which reads from the input buffer the cancel or confirm reload command and, if necessary, save the configuration.
Tickle does not support typing, it must be remembered when operating with variables:

The nested operator
[expr {..}]
calculate the value of the expression specified in curly brackets ($ a + $ b) and perform the substitution of this value instead of square brackets.
Sample procedure in Tcl:
proc ping_net {x} {
for {set n 1} {$n < $x} {incr n} {
exec "ping 192.168.0.$n"
}
}
when entering a curly bracket, the interpreter will not close the command line until a pair of closing brackets is entered. The procedure is stored in the interpreter's memory until the interpreter session is terminated with the tclquit command. This makes it possible to run procedures and access variables of previously running scripts. Remember that an error in the script can lead to looping and locking your session (V) TTY! The console does not have emergency shutdown tools (such as Ctrl + Break), the only way is a new session and resetting a hung session with the
clear line
command.
We now turn to solving a practical problem. Before us is the 48-port Cat2950S "out of the box." Script below
- requests from the console the serial number of the switch sw_num
- sets hostname of the form switch_ <sw_num>
- requests and sets a password to the priveleged EXEC console
- adjusts the address on its control interface Fa0 (192.168.0.x) and interface Vlan1 (10.0.x.254) according to 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 low 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. This script has a small logical error. Try to find it.
Note 2. Some text editors like to put an unprintable EoF character at the end of a file. You can see it in the IOS console by displaying the contents of the file with the command cat or more. Stumbling on EoF, the Tcl interpreter will generate an error and ignore the entire line. Therefore, I left a comment at the end of the script.
The question arises: how to write the script in the memory of the switch with unconfigured IP working only through the console port? Do not type the script with your hands! Is it possible to manually configure the Management Interface and use FTP every time? No, it can be easier. Cisco IOS can copy files directly through the serial port of the console via the Xmodem protocol and save them to the flash. To do this, you will 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 “demolish” the switch configuration without having a password on the priveleged EXEC). But the reverse copying of files (from the flash memory of the switch on the PC) is not supported.
Unfortunately, you cannot open a telnet session from a Tcl to a remote router. Upon attempt
sw(tclsh)#exec "telnet host"
session just hangs during password input.
This concludes the introduction of the Tcl language capabilities on the Cisco IOS platform, you can explore the issue in more detail in the Cisco IOS Scripting with TCL Configuration Guide available on the Cisco website.