In order to provision an embedded device (i.e. writing images to flash) a series of very well known commands have to be entered during the boot stage. The algorithm is something like:

  • Capture a bootloader shell by entering any key during boot
  • Flash image A
  • Flash image B
  • ...
  • Continue Boot (with new images)

Since we must first capture the bootloader shell at a certain point in the boot process I figured application of an expect script would solve this problem nicely. I also would like to mix some other bash commands for implementing the logic regarding which device node to connect to, etc. What I came up with (expect portion only) is the following:

#Other bash stuff

expect <<SCRIPT
    set timeout 5
    spawn plink -serial -sercfg 115200,8,n,1 $DEVICE 

    expect "Hit any key to stop autoboot"
        sleep 1
        send "\r"

    expect "=>"
        sleep 1
        send "$FLASH_CMD_A\n"


echo "Done!"

What I am observing is: The first expect line is properly being captured, the sleep is working, and the newline appears to be being sent. The next expect (capturing the prompt) and its corresponding sleep also appears to be working. The send command ($FLASH_CMD_A) gets printed to the terminal with lots of white spaces between words, but it seems to be working also.

The biggest problem is that the interact does not appear to be doing anything. Once the second expect/send is executed I am dropped back to a bash shell having never even seen "Done!" printed to stdout. I also tried the interact syntax:

interact {
        send "\r"

But that did not work at all. The prompt was never captured and the script just exited immediately as if the interact statement were not there at all. Any ideas on what I may be doing wrong? I have:

expect -v
expect version 5.45

Although the commands seem to be being passed to the device I cannot be sure. Once I am dropped back to a bash shell all output from the device following those commands is lost. However, if I run my script a second time expect seems to dump its text buffer (expect_out?) and exit immediately. Interestingly, the output I was expecting from the previously sent commands is contained within this buffer dump.

As an aside: I tried this same script inside an VM environment and none of the "expect"ed statements were being captured; all input was printed to stdout and passed through.

  • Try to add expect eof after interact
    – Costas
    Commented Jul 11, 2016 at 16:44

1 Answer 1


As a workaround, run the expect script from a file, and not via standard input:


BLAH='echo hi'

ESCRIPT=`mktemp runner.XXXXXXXXXX` || exit 1

# nope
#expect -d - <<SCRIPT
  set timeout 5
  spawn $SHELL
  # FIXME whatever your prompt looks like
  expect -ex "% "
  send -raw "\r"
  expect -ex "% "
  send -- "$BLAH\n"
  expect -ex "% "

expect -d $ESCRIPT

echo alas poor $SHELL I knew him well a man of infinit

# and probably also `trap` in the event this code gets whapped with an INT
# or something...
  • Great workaround! For my usage case, I had to use expect -f instead. Commented Oct 28, 2020 at 23:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .