From the expect man page:

Expect is a program that “talks” to other interactive programs according to a script. Following the script, Expect knows what can be expected from a program and what the correct response should be. An interpreted language provides branching and high-level control structures to direct the dialogue. In addition, the user can take control and interact directly when desired, afterward returning control to the script.

At the institution for which I work, I am responsible for our Sungard HE Banner ERP system. One of the development tasks that I was presented with was to automatically run a binary file at 10pm every night. The challenge was that this program was interactive and required the user to input answers to prompts. This sounded like a perfect use of the Unix program expect.

If you are not a Sungard HE Banner ERP user, then skip the next two paragraphs. They’ll just be babble to you, and I’m sure you want to get to the good stuff about expect. For all of you Sungard HE Banner users reading this, the program I am calling is TGRCLOS. TGRCLOS is used to automatically close cashiering sessions, and I wanted to have the system close a certain set of cashiering sessions automatically at 10pm every night. This was so that the cashiering session we open for our online credit card payments that post directly into accounts receivable automatically closes at the same time our credit card processor (Intellipay) settles the transactions. Essentially, this was so that the cashiering session total matched what our credit card processor showed as being posted to a specific day.

By the way, someday I’ll post about how we developed our own poor man’s online credit card processing framework. This allows students to go into our portal, pull up their tuition bill, and pay online using a credit card. The payment also posts into Banner AR in real time. Its an awesome solution that really costs us nothing, just our standard credit card processing fees. It’s not the full blown TouchNet solution, but then again it didn’t cost us tens of thousands of dollars.

Now for the good stuff. Below is an overview of how I used expect. Keep in mind that this is all running on a RedHat AS 3 server, and if you don’t already have the expect binary installed then you will need to install it. My expect binary is in:

/usr/bin/expect

The first thing to do when you want to use expect to automatically interact with your program is to get all of the input prompts that the program asks for.

So I manually run the program I want to automate from my shell prompt. The command I want to automatically run is below, and I manually key that into my shell prompt to run it. Yours will probably be different.

tgrclos -o /home/banner/scripts/log/tgrclos.lis tarcher/mypassword

And the interactive output from my program looks like:

Connected.
Starting TGRCLOS (Release 7.3)

Run Sequence Number: 

(C)lose, (F)inalize Cashier Sessions or (B)oth: B

Run in (A)udit or (U)pdate Mode: U

Cashier Exception: 

Detail Category Code Exception: 

Close Sessions Containing Deposits [Y/N]: Y

Close Sessions Containing Misc. Transactions [Y/N]: Y

Number Of Printed Lines Per Page [55]: 

Enter "y" to proceed,
      "n" to respecify options,
      "x" to cancel report:      y

tgrclos completed successfully
87 lines written to /home/banner/scripts/log/tgrclos.lis

You can see that I had to answer a few prompts, and then the last two lines of output show the program running.

Now comes the fun part, writing the expect script to automatically interact with this program for me. Here are the steps:

1.First create a file with the extension .exp to hold your expect script.

vi run_tgrclos_for_sid.exp

2.Now in this file create the commands to spawn and interact with your program. My expect script looks like:

#!./expect -f
set timeout 30
spawn tgrclos -o /home/banner/scripts/log/tgrclos.lis $env(USERID)
expect "Run Sequence Number"
send "\r"

expect "(B)oth"
send "B\r"

expect "(U)pdate Mode"
send "U\r"

expect "Cashier Exception:"
send "\r"

expect "Detail Category Code Exception"
send "\r"

expect "Close Sessions Containing Deposits"
send "Y\r"

expect "Close Sessions Containing Misc. Transactions"
send "Y\r"

expect "Number Of Printed Lines"
send "\r"

expect "to cancel report:"
send "y\r"

#delay until a spawned process terminates
wait
The set timeout line just gives expect a timeout of 30 seconds in case it doesn’t find the prompt it is looking to fill in.

Then you need to spawn your program: This line in the expect script is what starts my program tgrclos working.

spawn tgrclos -o /home/banner/scripts/log/tgrclos.lis $env(USERID)

The -o /home/banner/scripts/log/tgrclos.lis $env(USERID) components are actually arguments to the tgrclos program I am running. It is nothing special to the expect script.

Also note that I use the special format $env(USERID) to get my userid and password string from an environment variable.

The next step is to write your expect script to expect a prompt, and then top provide a response. This is done through the series of expect and send lines.

For example, in my script I have:

expect "Run Sequence Number"
send "\r"

This tells expect to wait for the prompt text labeled Run Sequence Number, and then to just provide a carriage return (equivalent to just hitting the enter key) response.

Repeat your expect and send commands until you provided input to your entire program.

The last component of the expect script is the wait line which tells the expect program to wait until the spawned process terminates. We want to allow the TGRCLOS program to have a chance to finish running.

3.The last step is then to run your script. I do this through the commands:

export USERID=usfbanner/mypassword
expect run_tgrclos_for_sid.exp

You probably wont need the USERID environment variable export. I just needed it because of the $env(USERID) in my expect script.

Now you have a very simple overview of how to use expect. It can do A LOT more, and I’ve only scratched the surface of what can be done with this post.