Harnessing the Power of Expect: Automating Interactions with Ease
A guide to automating Terminal interactions using Expect
Expect is a robust scripting language designed to automate interactions with programs that require user input. For instance, if you need to run a program that asks the user to enter a password and supply arguments, Expect can handle this automatically. It operates by anticipating inputs and delivering the necessary responses without manual typing. This can be integrated into your shell scripts to enhance efficiency.
Let’s check it out in action!
Common Use Cases
Some of the most powerful uses cases of Expect script include:
Connecting to a remote server using SSH
Transferring files using SCP
Printing network response time
Executing the
fsck
command to verify your file system
In this short tutorial, we’ll have a look at how to log in to a remote server and execute a specified script.
Let’s get started!
Install Expect
Note that this tutorial is written for a Unix-based OS.
Some Unix-based systems already include Expect. Check if it is installed by executing this command in your Terminal:
which expect
If you need to install it, then execute one of the following commands based on your OS:
For Ubuntu distributions:
apt-get install expect
For Red Hat distributions:
yum install expect
For macOS— the easiest way is to use Homebrew:
brew install expect
Create an Expect Script SSH Program
Let’s say that you want to execute a bash script which sends an email to the administrator if a specific program has finished its output.
Create a file called
autoexecutor.exp
.Put the following content. (The code explanation is below.)
#!/usr/bin/expect set host [lindex $argv 0]; set user [lindex $argv 1]; set password [lindex $argv 2]; set remotecommand [lindex $argv 3]; eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no $user@$host set prompt ":|#|\\\$" interact -o -nobuffer -re $prompt return send "$password\r" interact -o -nobuffer -re $prompt return send "$remotecommand\r" interact -o -nobuffer -re $prompt return expect "#" send "exit\n"; exit 0 expect eof
Make sure that the Expect command path matches yours. In my case, it is
#!/usr/bin/expect
.We declare the variables we expect. The program requires a hostname, a username, a password, and the name of the script which we want to execute on the given remote server. They’ll be received as command-line arguments.
The
spawn
command is used to start a script or a program, in this case, SSH.Sometimes prompts are customized differently and there might be difficulties to automate the login if we don’t know the exact prompt. It’s a good practice to set the prompt using
set prompt
.The
interact
command reads input from the keyboard and returns the stdout and stderr of the current process.The
-o
flag applies any following key-body pairs to the output of the current process.The
-nobuffer
flag outputs characters that match a pattern as characters are read. Basically, it echoes back the pattern.The
-re
flag indicates a regular expression pattern.The
return
command makes interact to return to its caller.The
send
command, as its name suggests, sends a reply to our program — in this case, the password and the remote command. We also use it to exit from the server at the end of the script.To send the input characters,
“\r”
is used to denote a return character.The
expect
command waits for an input.The
eof
indicates the end of the script.
Run the script by providing the necessary arguments. We assume that the sendmail.sh
shell script exists on the remote server:
expect autoconnector.exp myhost myuser mypass /home/sendmail.sh
Conclusion
In conclusion, Expect stands out as a versatile tool for automating user interactions with command-line programs. By anticipating inputs and providing automated responses, it simplifies processes that would otherwise require manual input. Whether you're automating simple tasks or complex interactions, Expect offers a powerful solution to simplify and enhance your command-line operations.
I hope that you’ve learned something new. Thanks for reading and happy coding!