Boring Tasks Automation with Expect

Repetitive Tasks

It’s by human nature, we hate repetitive tasks! We always try to perform our job using the minimum actions possible. This is particularly true for Network or System administrators! There is nothing more boring than repetitive tasks…

A good example? In the scope of a new monitoring platform, fifty Cisco switches configuration to review and add a new Syslog destination. For those who are familiar with IOS, it’s something like:

# telnet switch-1
Trying x.x.x.x...
Connected to x.x.x.x.
Escape character is '^]'.


User Access Verification

Password: 

switch-1> en
Password:
switch-1# conf t
Enter configuration commands, one per line.  End with CNTL/Z.
switch-1(config)# logging a.b.c.d
switch-1(config)# ^Z
switch-1# wr
Building configuration...
[OK]
switch-1# exit
Connection closed by foreign host.

Really easy but so boring when you must perform the same action on all switches! Fortunately, a nice tool can save our time: Expect. The description on the homepage says everything:

Expect is a tool for automating interactive applications such as telnet, ftp, passwd, fsck, rlogin, tip, etc. Expect really makes this stuff trivial. Expect is also useful for testing these same applications. And by adding Tk, you can also wrap interactive applications in X11 GUIs.

Exactly what we need! The way Expect works is easy and based on two fundamental commands: “send” and “expect“. In clear, we establish a connection like a regular client (telnet, ftp, …), we send strings and expect some results. Expect uses Tcl as underlying language for conditions, procedures, loops, file I/O, and arithmetic expressions. So, let’s back to my example above (adding a new Syslog destination) and let’s write a small script:

#!/usr/bin/expect -f
# 
# This simple Expect script will add a new Syslog destination in
# Cisco switches (IOS based)
# We assume here that all switches uses the same credentials
# for the administrative tasks
#
# Define variables
set password "xxxxxxxxxx"
set enablepassword "xxxxxxxxxx"

# Define all the switches to be reconfigured (separated by spaces)
set switches "10.0.0.1 10.0.0.2 192.168.1.2 172.16.10.23"

# Main loop
foreach switch $switches {
	puts "Processing switch: $switch";
	# Open the telnet session:
	spawn telnet $switch

	# Perform authentication
	expect "Password:"
	send "$password\r"
	expect ">"

	# Switch to enable mode
	send "en\r"
	expect "Password:"
	send "$enablepassword\r"
	expect "#"
	
	# Enable configuration mode (terminal)
	send "conf t\r"
	expect "#"

	# Add a new syslog destination
	send "logging 10.11.12.13\r"
	expect "#"
	send "exit\r"
	expect "#"

	# Save config to NVRAM
	send "wr\r"
	expect "#"
		
	#Logging out
	send "exit\r"
	expect eof
}

Of course, they are requirements to use the script with success: All the devices must be IOS based (not CatOS), the access and enable passwords must be the same. But Expect is performant enough to read password and hosts from a file. Then we can have multiple passwords! [Security Notice: Expect uses your password in clear text, it means that the right (read “safe”) location must be defined to store your scripts]

Think about it, I’m sure you’ll find a lot of boring tasks which could be quite easily automated. Another nice example, backup of routers and switches to a TFTP server. Thanks to Steven who brought Expect back in mind! ;-)

All the required information about Expect is available on expect.nist.gov and a repository of free examples is available in the /scripts directory.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.