Expect

From Leo's Notes
Last edited on 13 July 2021, at 06:02.

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[edit | edit source]

Installation[edit | edit source]

Install expect on your system by running:

apt-get install expect

yum install expect

Quick start[edit | edit source]

There are two ways to write expect scripts:

  1. Write the expect script in a file with the #!/usr/bin/expect hash bang header and execute the script like any other shell script
  2. 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: set Username [lindex $argv 0]

Conditions[edit | edit source]

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[edit | edit source]

Use expect to telnet to a device and reboot it[edit | edit source]

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.


See Also[edit | edit source]