sandra_henrystocker
Unix Dweeb

Getting work done while you’re fishing — with expect

How-To
Aug 30, 20155 mins

Getting work done while you’re fishing — with expect

Not exactly an unknown command, but one that seldom reaches the Unix top ten, expect is an interesting Unix tool that allows you to run tasks that are designed to be interactive — even when you’re nowhere to be found.

For example, when an install script expects to collect a couple pieces of information from the person running it, you can set it up to run unaccompanied. When you have set up a series of automated tasks that need to be run before a new service goes live (and some of these require some interaction with the person running them), you can set them all to run overnight when no other service will be affected.

Obviously not your own scripts as, presumably, you can design those to accept parameters rather than question/answer sequences, expect can be very handy for everything from crafting an interaction between servers to running time-consuming installations that you’d prefer be done after hours.

Installing expect is easy. The expect package can be installed using one or the other of these commands on most Linux systems:

sudo yum install expect
sudo apt-get install expect

You’ll then find the tool in /usr/bin. So, you can start your expect scripts with the shebang line shown below.

#!/usr/bin/expect

You can run expect commands on the command line. The basic syntax is shown below.

expect [ -dDinN ] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]

Here are some examples of very basic expect commands:

$ expect -c 'expect "n" {send "hellon"}'

hello

Once the person at the keyboard presses the enter key, the system comes back and says “hello”.

$ expect -c 'expect "hi" {send "good morningn"}'
hi
good morning

In this one, expect is expecting you to type “hi”.

In either of the examples shown above, expect is only going to wait ten seconds before it gives up and drops you back to the command line. This is its default timeout. You can change that if you need to a longer or shorter time periond by using a set timeout command. No patience with someone expected to type “hi”? Give him only two seconds:

expect -c 'set timeout 2; expect "hi" {send "good morningn"}'

You can put your expect commands into scripts by using the shebang line shown above and your expect commands. This script will exit after ten seconds (default timeout) or as soon as you type “hello”.

#!/usr/bin/expect

expect hello

This one waits up to a minute and sends a friendly acknowledgement if you type “hello”. If the person running this script simply sits there sipping her coffee and doesn’t respond, however, the script will still send the friendly message.

#!/usr/bin/expect

set timeout 60
expect "hello"
send "Hello there, cutie!  What are you up to today?n"

Want to withhold the friendly message for anyone too crabby or too preoccupied with her morning coffee to type “hello”? No problem. Modify the script above with the added { and } and the friendly message will be dependent on a response.

#!/usr/bin/expect

set timeout 20
expect "hello" {
send "Hello there, cutie!  What are you up to today?n"

One of the most heavily used expect commands is spawn. In fact, for many expect scripts, the spawn command is the first thing you do as this command spawns some process that your script needs to interract with to get some important work done.

Say we have a script called “add” that adds two numbers together.

#!/bin/bash

echo -n "Enter the first number: "
read num1
echo -n "Enter the second number: "
read num2
sum=`expr $num1 + $num2`
echo $sum

And now we want out expect script to interract with that process.

#!/usr/bin/expect

set timeout 30

spawn "./add"

expect "Enter the first number:" { send "111r" }
expect "Enter the second number:" { send "365r" }

interact

Using commands such as these, you can provide information to the interactive processes that you want to run on their own in your absence.

Some of the other expect commands include:

  • expect — this command should be thought of as a loop. It waits for the string specified until it appears
  • send — sends a string to the process (or the screen)
  • send_user — sends output to standard out
  • log_user — can be used to stop output (log_user 0) or turn it back on (log_user 1)
  • exp_interval — provides a debug mode (exp_interval 1)
  • set — assigns values to variables
  • close — closes the connection to a process
  • interract — returns control to the user

When to use expect:

You should consider using expect …

  • only after you’ve tested the install on one system to make sure it works as expected (excuse the pun!)
  • only if the answers that you need to provide within your expect scripts don’t present any security risks (e.g., exposing passwords)

Expect scripts can get quite complicated and, yes, there’s an entire book written on the tool — Exploring Expect: A Tcl-based Toolkit for Automating Interactive Programs. http://shop.oreilly.com/product/9781565920903.do

sandra_henrystocker

Sandra Henry-Stocker was a programmer, Linux systems administrator, security engineer and Linux journalist for most of her 30-year career. She describes herself as "USL" (Unix as a second language) but remembers enough English to write books and buy groceries. She lives in the mountains in Virginia where, when not working with or writing about Unix, she's chasing the bears away from her bird feeders. Tune into her 2-Minute Linux video tutorials and take command of your command line.

More from this author