Expect is a wonderful tool. Many people use it without realising it's a Tcl extension. Many people use it when they don't actually need it. Many people who don't use it forget the convenient facilities it provides.
Primarily, Expect provides three things:
* [pty] support. This is Expect's big draw, allowing it to drive programs which were never intended to be automated. * [signal]s. A convenient way to add signal support to your scripts is `package require Expect; trap {puts {no interruptions!}} SIGINT` * the [expect] control structure and all its wonderful friends ([expect_background], [interact], ...). Not to be underestimated.
Traditionally, pty support is the big card that ties people to Expect. An incredibly common use-case is driving SSH connections to administer remote machines. Some anti-patterns in this scenario:
* using [expect] to send passwords: use key based authentication! * getting past the "unknown host key" message: use options `-q -o 'StrictHostKeyChecking no'` * if you're just running a single, non-interactive command, put it on the ssh command line and be done with it.
Crucially, OpenSSH doesn't actually require a local PTY! Just use the -t option, twice:
set user $::env(USER) set host localhost set ssh [open "|ssh -tt -q -o {StrictHostKeyChecking no} $user@$host /bin/sh" r+] ;# hint: not using a login shell can make output easier to consume fconfigure $ssh -buffering line -blocking 1 -translation lf while {[read $ssh 1] ne "$"} {} ;# wait for a prompt puts $ssh "uptime; exit" gets $ssh ;# consume the line we just sent set uptime [read $ssh] ;# read until EOF close $ssh puts "Uptime on $host: $uptime"
Automating complex interactivity without the expect command, you will quickly come to miss it. But if all you need to do is snatch some output, tail some logs or run a single command the above pattern can be useful. It allows you to ship your solution without a binary extension, and makes it more obvious how to use modern Tcl features like coroutines, Non-blocking IO and Channel Transformers.
The expect DSL is a bit awkward by modern Tcl standards, but it's excellent for abstracting protocol interaction. Today, it should probably be rewritten in pure Tcl, using up-to-date idioms, TclOO and coroutines ... but there is a lot of non-obvious wisdom embedded in the design of Expect which is non-trivial to extract.