Version 19 of Expect Examples

Updated 2006-01-21 01:19:57

Expect comes with a bunch of examples that are indispensable and unique full-function tools in their own right like cryptdir, passmass, unbuffer, kibitz, dislocate, etc, etc.

The latest cool new Expect whizbang: multixterm.

LV offers an example of his use of Expect: "Our local public library used to have a telnet interface to its patron account system. I wrote an Expect script which logged onto the system, queried for the holdings status of each account in my family, then logged off. I would run this from cron and get a report as to which books were coming up for return, what items were held for pick up, and so on. I then placed the text version of that report into a directory where a daily sync to my Palm Pilot would result in a PalmOS memo containing this info."


Category Expect

Can I add to this web page? AK: Of course.

This is how you send ctrl+C through expect: send \003


The Let's Grab Everything Example by Froggy

Oftentimes I just want to grab all output and do as I wish with it afterwards. This example will demonstrate how to grab everything from a shell command. In this example, I launch the bash shell with the spawn command, then I send commands to the bash shell with exp_send, and finally I use expect to get retrieve my results.

    # load the Expect package into Tcl
    package require Expect

    spawn bash

    exp_send "ls -l\n"

    set accum {}
    expect {
        -regexp {..*} {
            set accum "${accum}$expect_out(0,string)" 
            exp_continue
        }
    }

    puts $accum

  • You must wait for this example to time out. It does not return right away. You can experiment with the -timeout option to expect. I think the default value is 10, but I am not sure.
  • When I say grab everything, I mean everything. This will grab your prompt, your command, the command's results, and the prompt again, just like you see in the shell. To obtain the prompt, so that you can filter it out of your output, put an expect construct immediately after your spawn command. This will grab the prompt that shows up when you first launch the shell. Assign accum to some variable like "prompt".
  • If the only thing you want to do with this shell is get a file listing, or if the state of the shell is already set up before you run the Tcl Script, simply use spawn "ls -l" or even set processHandle [open "|ls -l 2>&1" RDONLY]. My example is good for long-running programs like ssh, a serial session to a PLC, ftp or shell sessions where scripts that set up the environment must be run. This would be a really simple way to set up your own little GUI POP3 client (not like we're lacking those).
  • MUY IMPORTANTE: If you want to use this inside a modularized program (imagine that), you MUST call spawn at the global level. Ie., uplevel #0 {spawn bash}. If you do not, expect will not find any results. As a matter of fact, I don't think the command issued by exp_send even executes. This is also true if you are using [incr tcl] RJ There are many ways to get around this. Globalizing the $spawn_id var is one, or using the -i switch with $spawn_id in exp_send works too. It is possible to spawn muliple sessions and interact with them by saving the spawn_id as you spawn new seesions then setting the spawn_id var as you need.
  • The -timeout option, if added will be executed by expect.
  • Be sure to put \n after your command. If you don't, it's just like you forgot to hit enter at the keyboard. [Wandering by, CL wonders if \r wouldn't serve even more correctly.]
  • You don't need the "package require Expect" line if you are using the Expect executable. You need it for wish or tclsh.
  • If you are not familiar with expect_out, it is an array. Try array names expect_out at the tcl shell prompt.
  • -regexp option look strange? Check out regular expressions.

RJ Here's a simpler way to catch all of the output:

   proc exec_it {command}     {
      spawn -noecho $command 
      log_user 0
      expect eof
      return [string trimleft $expect_out(buffer) $command]
   }
  • The trimleft will just remove the echoed command from the output.

COSI-NMS [L1 ] is a SourceForge-hosted project to which Cisco contributes. Several of the Cisco-specific examples which appear there are Expect scripts.


LV Here's a question from an expect developer:

 #!/usr/bin/expect  --
 set timeout 30
 spawn /usr/local/bin/scp -P 36000 user@ip:/data/myfile  /data1
 expect "password:" {
  send "password\r"
 } "yes/no)?" {
  send "yes\r"
  set timeout -1
 } timeout {
  exit
 } eof {
  exit
 }

when scp executes normally, everything is ok. But when the host does not exist, or is not reachable, the script stops, waiting for the "password" prompt. Because the file to be copied is very large, the code needs to cancel the timeout. How would one get the result of scp so as to handle this properly? RJ Larry, made some changes to above - see if that does what you need. Also, if you only get the end of the file, try expanding the buffer with the match_max command right after the spawn.


Another example/question?

 #!/usr/bin/expect  --
 spawn /usr/local/bin/scp /home/user/bkp/*gz user@ip:/data/bkp/
 expect "password:"
 send "password\r"
 expect eof

Is the double dash on first line significant? The * in "/home/user/bkp/*gz" appears to be the cause of "No such file or directory" error. I've tried adding slashes, but it doesn't help.


Category Example - Category Expect - Category Networking