In my previous post I talk about needing a TFTP server in order to serve some files to a hardware device. This post describes how I used expect to automate the process of logging into the hardware device and issue commands that copy in a config file, commit it to the device, upgrade the firmware and finally tell the device to reset to factory defaults and reboot.

Expect is a way to programmatically work with a normally interactive process. Using expect you can write a script that telnets into a system and then issues commands based on what it “sees.” Here is the script I used, with some important values removed, to automate the process of updating a number of devices.

#!/usr/bin/expect
set timeout 300
spawn telnet 192.168.1.1
expect "login: "
send "root\n"
expect "Password: "
send "tehmagicphrase\n"
expect "# "
send "cd /tmp \n"
expect "# "
send "tftp -g -r config.ini 192.168.1.159\n"
expect "# "
send "config.sh import config.ini\n"
expect "# "
send "tftp -g -r firmware.img 192.168.1.159\n"
expect "# "
send "firmware_upgrade /tmp/firmware.img 1\n"
expect EOF

The above script was saved into a file called pushConfig.expect and set as executable using ‘chmod +x pushConfig.expect’. To run the script, I powered on the device and waited for it to be ready, once ready I issued ./pushConfig.expect to start the update process.

Using expect is fairly straightforward. The most difficult part is ensuring you correctly tell expect what to look for before sending the next command. In the script above I do the following:

set timeout 300

This tells expect to wait at least 5 minutes for matching text before continuing to the next send command. What this means, is if I tell it to send some data it’ll wait up to 5 minutes to see what is in the expect line after the send. In the case of my script the firmware upgrade could take quite a bit of time and I didn’t want it to timeout so I set the value fairly high.

The next line tells expect to start a telnet session to a remote machine and then to wait until it sees:

login: 

Once it sees that it sends the username. The script continues like this until it sees EOF. At this point expect knows that the process is now complete and it exits.

By using an expect script I was able to simply power on the hardware device and wait for it to boot. Once booted I ran the script. This saved me and a co-worker a lot of time while pushing custom configurations and upgrading the firmware on a number of devices.

Expect is capable of a lot more than I used in my example and can react differently based on what it receives back from the interactive process or even loop over a series of commands. To learn more about expect try ‘man expect’ or search your favorite search engine.

Ran into a situation today where I needed a tftp server in order to serve files to a hardware device. Normally I would have fired up a Linux system to get the job done but it hit me (again) that I’m using a UNIX operating system and it’s bound to have a tftp server built in. Sure enough I found it hiding on the system but I couldn’t get it to run. After some searching around I found my answer and I thought I’d post it so hopefully someone else will find it.

If you want to run the tftp server issue the following command:

sudo launchctl load -F /System/Library/LaunchDaemons/tftp.plist

This will cause the tftp server to load and stay running until it either crashes or you restart your system. If you want to ensure that tftp is always running issue the following:

sudo launchctl load -w /System/Library/LaunchDaemons/tftp.plist

To stop the tftp server issue the following command:

sudo launchctl unload /System/Library/LaunchDaemons/tftp.plist

To permanently disable tftp issue the following command:

sudo launchctl unload -w /System/Library/LaunchDaemons/tftp.plist