2 minute read Published:

Expect Script to Update Unix Group File

Expect scripts are useful when you need to interact with programs designed to work with a terminal interface. Not always an ideal way to get things done, but sometimes their is no better way to interact with said program. I had an incident recently where I needed to log into a server and add myself to a group. I couldn’t just log in as myself, I had to sudo before editing. Oh, and I had to do this on about a dozen boxes. The following is a list of things I learnt while writing my first Expect script.

Expect script are an extension of Tcl. If you want to get something done that is not specifically related to interacting with the terminal, for instance, looping, then you’ll be doing it with Tcl. That means, don’t search for “How to loop in Expect Script?”, instead search for “How to loop in Tcl?”. You’ll get much better results.

Sometime there are multiple outcomes for the same interaction. In my case, I was logging into boxes that I may or may not have logged into before. If I had not logged in, I would be asked if I trust the server (yes or no). Then I would be promoted to enter my password. You can cover this condition with a combination of nested expect statements and exp_continue.

expect {
    "yes/no" {
        send "yes\r"
        exp_continue
    }
    "*?assword" {
        send "$pass\r"
    }
}

If you don’t use exp_continue, when Expect finds either of the results it will break out. exp_continue means, carry on looking for other conditions. (You could have 3 or more conditions in one expect block.

If your script need a password, don’t enter password on command line. Plop this code in your script.

stty -echo
send_user -- "Enter your password:"
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set pass $expect_out(1, string)

When you are using the send command don’t forget \r. That’s how you simulate pressing the enter key and I mindlessly forgot it a couple of times.

This might seem trivial, but, make sure that the last thing you script does is checks for the final output. If you don’t wait the results might get eaten and you’ll be confused as to success of your script.

If you don’t want Expect to interpret a string add brackets ({}) around it.

Here is a good cheatsheet for quick reference. https://gist.github.com/Fluidbyte/6294378