expect

{{Short description|Extension to the Tcl scripting language}}

{{for|the South Korean professional gamer|Expect (gamer)}}

{{See Wiktionary|the Unix tool}}

{{more citations needed|date=May 2017}}

{{Infobox software

| name = Expect

| author = Don Libes

| developer = Nils Carlson

| latest release version = 5.45.4{{cite web | url=https://core.tcl-lang.org/expect/home | title=Expect | date=February 4, 2018 | access-date=May 18, 2025}}

| latest release date = {{start date and age|2018|02|04|df=yes}}

| programming language = C

| operating system = POSIX, Windows

| license = Public domain{{cite web | url=https://core.tcl-lang.org/expect/file?name=license.terms&ci=tip | title=Expect License Terms | date=February 4, 2018 | access-date=May 18, 2025}}

| website = {{URL|https://core.tcl-lang.org/expect/}}

| discontinued = no

}}

Expect is an extension to the Tcl scripting language written by Don Libes.{{Cite book |last1=Nemeth |first1=Evi |url=https://books.google.com/books?id=HVQ-MxB4q7kC&dq=Expect+is+an+extension+to+the+Tcl+scripting+language+written+by+Don+Libes.&pg=PT660 |title=UNIX System Administration Handbook |last2=Snyder |first2=Garth |last3=Seebass |first3=Scott |last4=Hein |first4=Trent |date=2000-08-29 |publisher=Pearson Education |isbn=978-0-13-700291-7 |language=en}} The program automates interactions with programs that expose a text terminal interface. Expect, originally written in 1990 for the Unix platform, has since become available for Microsoft Windows and other systems.

Basics

Expect is used to automate control of interactive applications such as Telnet, FTP, passwd, fsck, rlogin, tip, SSH, and others.{{Cite web |url=https://www.howtogeek.com/devops/automate-inputs-to-linux-scripts-with-the-expect-command/ |title=Automate Inputs to Linux Scripts With the expect Command |last=Mckay |first=David |date=May 24, 2021 |orig-date=May 24, 2021 |series=category/Linux |access-date=Nov 28, 2023 |language=en}} Expect uses pseudo terminals (Unix) or emulates a console (Windows), starts the target program, and then communicates with it, just as a human would, via the terminal or console interface.{{Cite book |last1=Carling |first1=M. |url=https://books.google.com/books?id=tK4oIcnngiUC&dq=pseudo+terminals+expect&pg=PA125 |title=Linux System Administration |last2=Degler |first2=Stephen |last3=Dennis |first3=James |date=2000 |publisher=Sams Publishing |isbn=978-1-56205-934-7 |language=en}} Tk, another Tcl extension, can be used to provide a GUI.{{Cite web |title=Tcl/Tk in the Development of User-Extensible Graphical User Interfaces |url=https://www.usenix.org/legacy/publications/library/proceedings/tcl96/full_papers/skinner/skinner.html |access-date=2022-08-11 |website=www.usenix.org}}

Usage

{{how-to|section|date=December 2020}}

Expect serves as a "glue" to link existing utilities together. The general idea is to figure out how to make Expect use the system's existing tools rather than figure out how to solve a problem inside of Expect.

A key usage of Expect involves commercial software products. Many of these products provide some type of command-line interface, but these usually lack the power needed to write scripts. They were built to service the users administering the product, but the company often does not spend the resources to fully implement a robust scripting language. An Expect script can spawn a shell, look up environmental variables, perform some Unix commands to retrieve more information, and then enter into the product's command-line interface armed with the necessary information to achieve the user's goal. After retrieving information by interacting with the product via its command-line interface, the script can make intelligent decisions about what action to take, if any.

Every time an Expect operation is completed, the results are stored in a local variable called $expect_out. This allows the script to harvest information to feedback to the user, and it also allows conditional behavior of what to send next based on the circumstances.

A common use of Expect is to set up a testing suite for programs, utilities or embedded systems. DejaGnu is a testing suite written using Expect for use in testing. It has been used for testing GCC and remote targets such as embedded development.

Expect script can be automated using a tool called 'autoexpect'. This tool observes your actions and generates an Expect script using heuristics. Though generated code may be large and somewhat cryptic, one can always tweak the generated script to get the exact code.

  1. Assume $remote_server, $my_user_id, $my_password, and
  2. $my_command were read earlier in the script.
  1. Open a Telnet session to a remote server, and wait
  2. for a username prompt.

spawn telnet $remote_server

expect "username:"

  1. Send the username, and then wait for a password prompt.

send "$my_user_id\r"

expect "password:"

  1. Send the password, and then wait for a shell prompt.

send "$my_password\r"

expect "%"

  1. Send the prebuilt command, and then wait
  2. for another shell prompt.

send "$my_command\r"

expect "%"

  1. Capture the results of the command into a variable. This
  2. can be displayed, or written to disk.

set results $expect_out(buffer)

  1. Exit the Telnet session, and wait for a special
  2. end-of-file character.

send "exit\r"

expect eof

Another example is a script that automates FTP:

  1. Set timeout parameter to a proper value.
  2. For example, the file size is indeed big and the network
  3. speed is really one problem, you'd better set this
  4. parameter a value.

set timeout -1

  1. Open an FTP session to a remote server, and
  2. wait for a username prompt.

spawn ftp $remote_server

expect "username:"

  1. Send the username, and then wait for a password prompt.

send "$my_user_id\r"

expect "password:"

  1. Send the password, and then wait for an 'ftp' prompt.

send "$my_password\r"

expect "ftp>"

  1. Switch to binary mode, and then wait for an 'ftp' prompt.

send "bin\r"

expect "ftp>"

  1. Turn off prompting.

send "prompt\r"

expect "ftp>"

  1. Get all the files

send "mget *\r"

expect "ftp>"

  1. Exit the FTP session, and wait for a special
  2. end-of-file character.

send "bye\r"

expect eof

Below is an example that automates SFTP (with a password):

  1. !/usr/bin/env expect -f
  1. Procedure to attempt connecting; result 0 if OK, 1 otherwise

proc connect {passw} {

expect {

"Password:" {

send "$passw\r"

expect {

"sftp*" {

return 0

}

}

}

}

# Timed out

return 1

}

  1. Read the input parameters

set user [lindex $argv 0]

set passw [lindex $argv 1]

set host [lindex $argv 2]

set location [lindex $argv 3]

set file1 [lindex $argv 4]

set file2 [lindex $argv 5]

  1. puts "Argument data:\n";
  2. puts "user: $user";
  3. puts "passw: $passw";
  4. puts "host: $host";
  5. puts "location: $location";
  6. puts "file1: $file1";
  7. puts "file2: $file2";
  1. Check if all were provided

if { $user == "" || $passw == "" || $host == "" || $location == "" || $file1 == "" || $file2 == "" } {

puts "Usage: \n"

exit 1

}

  1. Sftp to specified host and send the files

spawn sftp $user@$host

set rez [connect $passw]

if { $rez == 0 } {

send "cd $location\r"

set timeout -1

send "put $file2\r"

send "put $file1\r"

send "ls -l\r"

send "quit\r"

expect eof

exit 0

}

puts "\nError connecting to server: $host, user: $user and password: $passw!\n"

exit 1

Using passwords as command-line arguments, like in this example, is a huge security hole, as any other user on the machine can read this password by running "ps". You can, however, add code that will prompt you for your password rather than giving your password as an argument. This should be more secure. See the example below.

stty -echo

send_user -- "Enter Password: "

expect_user -re "(.*)\n"

send_user "\n"

stty echo

set PASS $expect_out(1,string)

Another example of automated SSH login to a user machine:

  1. Timeout is a predefined variable in Expect which by
  2. default is set to 10 seconds.
  3. spawn_id is another predefined variable in Expect.
  4. It is a good practice to close spawn_id handle
  5. created by spawn command.

set timeout 60

spawn ssh $user@machine

while {1} {

expect {

eof {break}

"The authenticity of host" {send "yes\r"}

"password:" {send "$password\r"}

"*\]" {send "exit\r"}

}

}

wait

close $spawn_id

Alternatives

Various projects implement Expect-like functionality in other languages, such as C#, Java, Scala, Groovy, Perl, Python, Ruby, Shell and Go. These are generally not exact clones of the original Expect, but the concepts tend to be very similar.

= C# =

  • [https://web.archive.org/web/20131224094314/http://blog.iwanek.eu/expect-net/ Expect.NET] — Expect functionality for C# (.NET)
  • [https://github.com/CBonnell/dotnetexpect DotNetExpect] — An Expect-inspired console automation library for .NET

= Erlang =

  • [https://github.com/hawk/lux lux] - test automation framework with Expect style execution commands.

= Go =

  • [https://github.com/google/goexpect GoExpect] - Expect-like package for the Go language
  • [https://github.com/Netflix/go-expect go-expect] - an Expect-like Go language library to automate control of terminal or console based programs.

= Groovy =

  • [https://github.com/iTransformers/expect4groovy expect4groovy]  - a Groovy DSL implementation of Expect tool.

= Java =

  • [https://github.com/Alexey1Gavrilov/ExpectIt ExpectIt] — a pure Java 1.6+ implementation of the Expect tool. It is designed to be simple, easy to use and extensible.
  • [https://github.com/cverges/expect4j expect4j] — an attempt at a Java clone of the original Expect
  • [http://expectj.sourceforge.net/ ExpectJ] — a Java implementation of the Unix expect utility
  • [https://github.com/ronniedong/Expect-for-Java Expect-for-Java] — pure Java implementation of the Expect tool
  • [https://github.com/iTransformers/expect4java expect4java]  - a Java implementation of the Expect tool, but supports nested closures. There is also wrapper for Groovy language DSL.

= Perl =

  • [http://sourceforge.net/projects/expectperl Expect.pm] — Perl module (newest version at [https://metacpan.org/pod/Expect metacpan.org])

= Python =

  • [https://github.com/pexpect/pexpect Pexpect] — Python module for controlling interactive programs in a pseudo-terminal
  • [https://pypi.python.org/pypi/winpexpect winpexpect] — port of pexpect to the Windows platform
  • [https://github.com/fgimian/paramiko-expect paramiko-expect] — A Python expect-like extension for the Paramiko SSH library which also supports tailing logs.

= Ruby =

  • [https://web.archive.org/web/20170311165445/http://rubyforge.org/projects/rexpect RExpect] — a drop in replacement for the expect.rb module in the standard library.
  • [https://github.com/jesnault/expect4r Expect4r] — Interact with Cisco IOS, IOS-XR, and Juniper JUNOS CLI

= Rust =

  • [https://crates.io/crates/rexpect rexpect] - pexpect-like package for the Rust language.

= Scala =

  • [https://github.com/Lasering/scala-expect scala-expect] — a Scala implementation of a very small subset of the Expect tool.

= Shell =

  • [http://empty.sourceforge.net Empty] — expect-like utility to run interactive commands in the Unix shell-scripts
  • [https://github.com/clarkwang/sexpect sexpect] — Expect for shells. It's implemented in the client/server model which also supports attach/detach (like GNU screen).

References

{{reflist}}

Further reading

  • {{cite book

| last = Libes

| first = Don

| year = 1995

| title = Exploring Expect: A Tcl-Based Tool for Automating Interactive Programs

| publisher = O'Reilly Media

| isbn = 1-565-92090-2

| url-access = registration

| url = https://archive.org/details/exploringexpectt00libe

}}

  • {{cite magazine

| magazine=Linux Gazette, (a member of the Linux Documentation Project (LDP))

| url=https://www.tldp.org/LDP/LG/issue48/fisher.html

| title=Advanced Programming in Expect: A Bulletproof Interface

| first=David

| last=Fisher

| date=1999

| publisher=issue of the Linux Gazette

| issue=48}}