Image of terminal

Expect Scripting For Network Engineers (Cisco)

Have you ever spent a good portion of your day repeatedly logging into all of the network devices in your data center to add the IP address of a new syslog server? Or perhaps removing the local user account of a former peer who jumped ship to greener pastures?

As a Network Engineer there have undoubtedly been times when you have had to make the same configuration change to a large group of devices. Unless you spent a few years honing your scripting skills as a Systems Administrator in the past, chances are that your idea of “automating” the process involved manually logging into devices and pasting the same configuration from a text file over and over.

You know that scripting could help, but who has time to learn to write code when you’re busy researching connectivity issues? After all you’re a Network Engineer and not a Developer, right?

Why Use Expect?

1. It’s Easy!

Expect is a scripting program written in Tcl that was built to automate tasks for other interactive programs, such as Cisco’s IOS and NX-OS command line interfaces. It’s rather intuitive to understand at the basic level.

Once you have a working baseline script, such as the one I am providing below, it’s fast and easy to modify it for use in any situation where you need to make the same configuration change on multiple devices.

2. It’s Already Installed

If you’re primary workstation is a Mac then there is no installation necessary! Expect is already installed in /usr/bin/expect.

3. Excellent Online Resources Available

The more you use Expect, the more you’re going to want to do with it. Luckily you don’t need to take an online course or buy the O’Reilly Media book like you would with Python and Perl. You can Google search your way to just about anything.

Simple Expect Script For Cisco Network Devices

I’m sharing a basic Expect script which you can use to make configuration changes to Cisco IOS and NX-OS devices from a Mac. If you want to run it from a Linux server, just update the path from /usr/bin/expect to wherever the program is located locally.

The script simply establishes an SSH session, enters enable mode (if you’re not already dropped in it), enters configure mode, sends whatever commands you specify, then does a write to memory before exiting and moving onto the next device. You need three files to accomplish this:


This is simply a text file with IP addresses and/or hostnames of the devices with which you want the script to connect to:

This is a bash shell script which you will run to start the entire process. It will prompt for your ssh password and an enable password, and then feed it to the Expect script along with the contents of device_list.txt. I found this more secure then reading the passwords from a file and easier to do in bash than in expect.

 # Collect the current user's ssh and enable passwords
 echo -n "Enter the SSH password for $(whoami) "
 read -s -e password
 echo -ne '\n'
 echo -n "Enter the Enable password for $(whoami) "
 read -s -e enable
 echo -ne '\n'
# Feed the expect script a device list & the collected passwords
for device in `cat device-list.txt`; do
 ./configure-cisco.exp $device $password $enable ;


This is the expect script that I explained earlier. It has some intelligence built in to gracefully handle ssh connectivity issues and will send results both to the screen and to a file called results.log in your home directory:

#!/usr/bin/expect -f

# Set variables
 set hostname [lindex $argv 0]
 set username $env(USER)
 set password [lindex $argv 1]
 set enablepassword [lindex $argv 2]

# Log results
 log_file -a ~/results.log

# Announce which device we are working on and at what time
 send_user "\n"
 send_user ">>>>>  Working on $hostname @ [exec date] <<<<<\n"
 send_user "\n"

# Don't check keys
 spawn ssh -o StrictHostKeyChecking=no $username\@$hostname

# Allow this script to handle ssh connection issues
 expect {
 timeout { send_user "\nTimeout Exceeded - Check Host\n"; exit 1 }
 eof { send_user "\nSSH Connection To $hostname Failed\n"; exit 1 }
 "*#" {}
 "*assword:" {
 send "$password\n"

# If we're not already in enable mode, get us there
 expect {
 default { send_user "\nEnable Mode Failed - Check Password\n"; exit 1 }
 "*#" {}
 "*>" {
 send "enable\n"
 expect "*assword"
 send "$enablepassword\n"
 expect "*#"

# Let's go to configure mode
 send "conf t\n"
 expect "(config)#"

# Enter your commands here. Examples listed below
 #send "tacacs-server host\n"
 #expect "(config)#"
 #send "tacacs-server directed-request\n"
 #expect "(config)#"
 #send "tacacs-server key 7 0000000000000\n"
 #expect "(config)#"
 #send "ntp server\n"
 #expect "(config)#"
 #send "ip domain-name\n"
 #expect "(config)#"

 send "end\n"
 expect "#"
 send "write mem\n"
 expect "#"
 send "exit\n"
 expect ":~\$"

To run the script, create all three files in your Mac home directory, chmod+x the scripts, then run

[12/07/2012 1:45pm @paul-mac-air:~]% ./
 Enter the SSH password for paul
 Enter the Enable password for paul
>  Working on @ Fri Dec  7 13:45:22 PST 2012 <
spawn ssh -o StrictHostKeyChecking=no

Examples of Simple Enhancements

The scripts I included above have been stripped down to the bare essentials so that there are fewer lines of code to get started with. It gets the job done, but the more you use the scripts the more you may want to enhance it.

I am by no means an expert in Expect or Bash, but I’ve spent a little time playing with both to help tailor my scripts to do the things I want. The more you use Expect, the more you may want to tailor it as well. Below are a few very basic examples.

1. Add terminal vt100 to for connecting to Nexus devices

I simply got tired of seeing this line every time I connected to a Nexus device:

Nexus 5000 Switch
Bad terminal type: “xterm-256color”. Will assume vt100.

You can specify a terminal type of vt100 by adding this line to the script (assuming you don’t want to do it in your terminal settings):

# Set terminal to vt100 so Nexus devices don't complain
export TERM=vt100

2. Save and rotate logs

I like to log all of the input from my script to a single file called “results.log” which I can then parse later and/or save for reference. To make sure I don’t overwrite a previous log file, I added a few lines of code to to copy and rename “results.log” to “results.log.timestamp”

timestamp=`date +%m%d%H%M`

# This will rotate and append date stamp...
cp $logfile $newlogfile


Expect is the perfect tool for easily automating redundant tasks and configuration changes on network equipment. It’s preloaded on Mac OS X and simple to install on server running the Linux flavor of your choice. You don’t need to fully dive in to the language in order to take advantage of it’s time saving capabilities.

// ]]>


  1. Hi there,

    At first I want to thank you for sharing this wonderful script. It saved me a lot of research time, since it perfectly fits my needs till the login-part was done.

    Currently I am working on a troubleshooting-system which monitors interfaces’ health and displays the ports on a website depending on their status (good, alert, critical). Later on, I want the system to repair itself on logical base. If you have to check for physical issues you (the network specialist) get contacted.

    Although your post is several years old: If you are interested in working together, please feel free to contact me via e-mail. I also do have some more ideas about Cisco automatization.

    Thankful regards

  2. I know this is an older post, but I’m trying to get this setup and going.

    When I run it prompts for passwords then quits with:

    “: no such file or directory

    I’m not super versed on scripting, so I might be missing something stupid simple.

    Things I’ve checked:

    All three files are in the same directory. CHMOD applied appropriately.

    Things I’ve modified:

    I’ve changed the script to allow for using one of our Tacacs usernames.

    I’ve changed the configure-cisco.exp script to reflect the username rather than whoami response.

    I did some tweaking to the log file for the expect script, not sure if this works, haven’t gotten this far.

    set Directory ~/logs

    # Log results
    log_file -a $Directory/session_$hostname.log
    send_log “### /START-SSH-SESSION/ IP: @hostname @ [exec date] ###\r”

  3. Dude, you are amazing! I really appreciate your work!

    It works like a charm. I would like to thank you for sharing such knowledge.

    Best regards,

    Luiz Oliveira

  4. Thanks for the Great work , I can use it with static passwords but not with RSA secureid (PIN+token) please share any example thanks

  5. Paul hi i Need your help now for meine expect script ,i run this script in my bash for creat vlan Switch but alles Dialoge in Switch Show in my bash .thas means i dont like return script Switch in my bash .please help me

  6. Hi all
    am new in expect script ,i need your help for my my script i ask for configure switch (for creat automaticaly vlan and tunking vlan ) its good works. in secondly i said in output show running,its works too,but in finally i want ask user “Are u sure configuration is finished ? ” its for checking configure switch ,if yes exit and if not can return ,but i cant write end of part script

    please help me for finally step,can you say where is my problem ?

    here is my script :
    #!/usr/bin/expect -f
    #set variables
    set hostname …
    set username..
    set ip …
    foreach hostname [array names interface] {
    set timeout 10
    match_max 500000
    # Log results
    log_file -a ~/results.log

    send_user “\n”
    send_user “>>>> Working on $hostname @ [exec date]<<<< \n"
    send_user "\n"
    spawn ssh -2 -o strictHostKeyChecking=no $username\@$ipaddress
    expect "username:"
    send "$username\r"
    expect "#"
    expect "password:"
    send "$password\r"
    expect -re $prompt
    #enable configure mode
    send "conf t\n"
    expect "(config#)"
    #vlan trunking mode
    send "$interface($hostname)\n"
    expect "(config-if-range)#"
    send "switchport access vlan 9\n"
    expect "(config-if-range)#"
    send "switchport trunk encapsulation dot1q\n"
    expect "(config-if-range)#"
    send "switchport mode trunk\n"
    expect "(config-if-range)#"
    send "switchport trunk allowed vlan 7\n"
    expect "(config-if-range)#"
    send "end\n"
    expect "#"
    send "write mem\n"
    expect "#"

    send "terminal length 0\r"
    expect "#"
    send "show running-config\r"
    expect "#"
    set output $expect_out(buffer)
    #Here dont working
    exp_sleep 1
    stty echo
    send_user — "Are you sure configuration is finished?(Y/n):\n"
    expect_before "(yes/no)?"
    send_user — "\n
    if [ "$(#)" != "yes" ];then
    [ send_user "exit\n" ]
    expect "#"
    exp_send — "\n"

    puts "$output"
    expect eof

  7. Hallo, Paul,

    Your Expect script is very popular and gets cited a lot, quite often.

    Because it has staying power it would help greatly to update it to patch the fairly large security hole in the SSH connection steps. Specifically the StrictHostKeysChecking must be set to either “accept-new” or “yes”. Otherwise with it set to “no” it leaves the connection vulnerable to a man-in-the-middle attack such that if an attack occurs, it will have 100% success. Having it set to “no” does not in itself increase the risk of MitM, unless someone finds out about the setting, but it ensures that any MitM attack will always succeed.

    A second matter would be to encourage the use of keys for authentication instead of passwords, but that is another matter. However, the important part would be to fix the StrictHostKeysChecking setting to reduce the risks for the copy-pasta crowd.

  8. Thanks for posting the script Paul, can you let us know when you update the StrictHostKeysChecking? Also if I want to remove a username account using the script and it asks me to hit confirm, what would be the command for that in the cisco.exp file? I have the no username portion working, but the script fails when the switch waits for the confirmation or the pressing of the return button on the keyboard.

  9. Hi Paul,
    Thanks for your sharing knowledge. That is very wonderfull. I have an question, do we can runninh expect with variable to change current vlan to new vlan. For eq : I want to automatiy change every vlan 10 in every interface will be change to vlan 20.

  10. Hi Paul,

    Thanks for sharing the scripts.

    I’m trying to use it, but I get the following error:

    line 17: ./script.exp: Permission denied

    line 17 is:
    ./script.exp $device $username $password ;

    The permissions of the expect file are:

    -rwxrwxrwx. 1 xxx xxx 933 Aug 6 17:05 script.exp

    I’m not sure what I’m missing here, probably something trivial.

    I’d appreciate any guidance.

  11. For those who try to use tftp and transmission stops after few blocks (tftp server says error “Interrupted by client, received error packet with code: 0 and message: Session terminated”)
    I have added line set timeout 1200 in file configure-cisco.exp (section # set variables)
    you can change it to 3600 (1 hour for big files and slow connections)

Leave a Reply

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

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

Google photo

You are commenting using your Google 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 )

Connecting to %s