In this tutorial, tasks will be automated using Expect.
Expect is an automation scripting language. It allows you to emulate each keystroke in a session. You type in commands to be delivered and responses to anticipate (or expect). When anticipated responses are received, you enter another command. This process is repeated until termination of the script.
The Expect script is the entire automated two-way conversation. In an Except script, dialog from both sending and receiving computers is scripted. A common use of Expects scripts is to automate SSH sessions between a local computer and a remote server.
Setting Up Expect
Except is available as an installable software package for most Linux distros. Use the package manager to download and install Expect along with any associated packages and/or dependencies.
If you’re using Ubuntu, enter the following string at the command line prompt to install Expect:
$ apt-get install expect
If you’re using CentOS, enter the following:
# yum install expect-devel
This may take some time but once it’s installed Expect may be run from the terminal.
Writing a SSH Script in Expect
You will need to write both ends of the “dialog”. This means that you must write the commands which you wish to send in the session and the responses anticipated from the remote server. In order to be run the script must be rendered executable. In order to make the Expect script an independent executable program three steps must be fulfilled. The location of Expect must be included in the script.
Assuming that the location of Expect on your system is /usr/bin/expect enter the following as the first line in your Expect script:
- The shebang (#!) Is required in order to specify Expect as the program used to interpret the script.
- The –f switch is used to tell Expect that it will be reading commands from the file.
The script must be saved as a shell file (.sh). In this example we’ll save it as expscript.sh.
Make the script executable.
This requires changing permissions on the script file, allowing it to be executable.
Enter the following at the terminal to modify permissions on the file, making it executable.
$ chmod 755 expscript.sh
The second line in your script uses the spawn command, which launches an external command. In this example, since we are dealing with SSH, the ssh command is used to start a SSH session with a remote server, “remote.server.com”.
spawn ssh remote.server.com
When attempting to connect to a remote server via SSH you will be prompted for a password. As we said before, Expect scripts are comprised of dialog from both machines, hence anticipated responses must be included in the script as well.
Anticipated responses must be precluded by the expect command and contained in double quotes:
expect "password: "
Note: Some servers will return “Password” with a capital ‘P’. If the scripts expects a common ‘p’ then this may cause the script to fail. As a workaround, a wildcard may be used. This line would be edited as follows:expect "*ssword: "
Or even more simply:expect "*: "
This method may be used for many anticipated responses from the remote machine. You will then have to enter your password. Commands which are to be sent from the local computer are precluded by the send command and, like anticipated responses, must be enclosed in double quotes. Additionally, sent commands must include a hard return (\r)at the end, within the double quotes.
Assuming a password of P@$$w0rd, the next line would be.
At this point you should be met with the user prompt so that should be stated as the expected information:
expect "$ "
At this point you may write out any list of commands which you would like executed, along with the anticipated responses from the remote server. At the end of your list of automated commands anticipate the user prompt and trigger an exit to close the session.
expect "$ " send "exit\r"
The entire script should therefore be:
#!/usr/bin/expect -f spawn ssh remote.server.com expect "password: " send "P@$$w0rd\r" expect "$ " ...... ##Various automated commands## expect "$ " send "exit\r"
Once the file is saved, remember to follow the instructions given above re modifying the permissions in order to render it executable.
Note: If you are having trouble with your script, try following it yourself and running it manually, making note of server responses to ensure that the anticipated responses you have in the script are accurate and that sent commands are error-free.
How to Easily Create an Expect Script
An excellent way of building an Expect script is to use a shell recorder program known as Autoexpect. Autoexpect works by recording a shell session. Each keystroke and shell response is recorded and written to an Expect script, script.exp.
Given the dynamic nature of computers, no two sessions may be completely alike so running the raw script generated from a single session may not work as expected when run again. As a result, most scripts generated via Autoexpect must be reviewed, edited and pruned in order to have the consistent desired effect.
If you’re using Ubuntu , run the following to install Autoexpect:
$ sudo apt-get install expect-dev
- This will download the utility and all required dependencies.
If you’re using CentOS, run the following to install Autoexpect:
# yum install expect-devel
To use Autoexpect enter the following:
Once Autoexpect is activated the following message will appear in your terminal:
Autoexpect started, file is script.exp
Each keystroke you type, and any subsequent responses displayed on screen, are recorded to the file script.exp and formatted in Expect script.
To stop Autoexpect, and stop recording to the script.exp file, press Ctrl-D.
The generated script.exp file will be very long, complete with the total transcript of the session and additional commentary. AS stated before, review and edit the generated file, testing it for any bugs. While this may take some time to get right it is easier, by far, than to attempt generating complex scripts by hand.
You now have a fully functional script to run repeatedly, as needed, with ease, and the means to easily produce more scripts.