Expect
Expect is a utility that makes it easy to automate commands that require user input via STDIN.
Places where I've used expect include automating fdisk, installers (like the Nvidia Linux driver), and telnet.
Introduction
Installation
Install expect on your system by running:
apt-get install expect
yum install expect
Quick start
There are two ways to write expect scripts:
- Write the expect script in a file with the
#!/usr/bin/expect
hash bang header and execute the script like any other shell script - Pass the expect script during execution, like most short
awk
scripts.
An example expect script would look like this:
#!/usr/bin/expect -f
set timeout -1
spawn passwd
expect "New password:\r"
send "new-password123\r"
expect "Retype new password:\r"
send "new-password123\r"
expect eof
Looking at this example script, it should be evident what the script does. Simply put, an expect script starts a program (with spawn
), then expects a certain string (expect
), and then sends a reply based on this condition (send
).
The commands that expect supports are listed below.
Command | Description |
---|---|
spawn
|
Starts a program or script |
expect
|
Wait for a specific program output |
send
|
Writes a reply to the program |
interact
|
Pass the program input to the user |
set
|
Sets a variable.
Eg. Username set to the first argument: |
Conditions
Conditional reply based on an expected string:
expect {
"*movie?" { send -- "The Godfather\r" }
"*song?" { send -- "Sandstorm\r" }
}
Conditional reply based on some variable:
if ( $Username == "leo" ) {
puts "leo\r"
} else {
puts "other\r"
}
Tasks
Use expect to telnet to a device and reboot it
I have a Wyze Cam which I sometimes would want to reboot if something stops working with it. To do so, use the following expect script (which I inlined as part of a bash shell script):
#!/bin/bash
if something-went-wrong ; then
expect -c "
set timeout 10
spawn telnet ${CAM_IP}
expect \"login:\"
send \"root\r\"
expect \"Password:\"
send \"${CAM_PASSWORD}\r\"
expect \"*# \"
send \"reboot\r\"
expect \"*# \"
exit"
fi
Note that the expect *#
after the reboot command is required. Without this final expect, expect will exit before the reboot gets triggered.