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 "hello\n"}' hello
Once the person at the keyboard presses the enter key, the system comes back and says "hello".
$ expect -c 'expect "hi" {send "good morning\n"}' 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 morning\n"}'
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 "111\r" } expect "Enter the second number:" { send "365\r" } 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