Search code examples
linuxbashshellexpectexecution

Bash/expect script to control execution


I am looking to control the flow of execution of a compiled C program X using bash scripting. The program X only produces text output and I want immediately pause execution when a certain string is printed. After this, I want to switch into bash and execute some commands and then return back into completing X. I have done some reading and testing and only expect/bash scripting seems to meet my needs. However, I am having difficulties achieving my goal.

I have tried spawning X within an expect script and then expect "mystring" followed by sending bash script commands but this only resulted in the bash commands being executed after X terminated.

Does anyone know the approach of achieving this? To clarify, I cannot use gdb in this situation.

#!/usr/bin/expect
spawn X
expect "mystring"
send -- "bash command"

Solution

  • I would spawn a shell instead of spawning X directly. Then you can use the shell to send a SIGSTOP to the program to pause it (unless the program has the capacity to pause when you send something directly to it).

    A demo

    #!/usr/bin/expect -f
    
    spawn bash
    send "unset PROMPT_COMMAND; PS1=:\r"    ;# I have a fairly tricky bash prompt
    expect -re ":$"
    
    # this stands-in for "X": start a shell that sends stuff to stdout
    send {sh -c 'n=1; while [ $n -lt 10 ]; do echo $n; sleep 1; let n=n+1; done'}
    send "\r"
    
    # when I see "5", send a Ctrl-Z to suspend the sh process
    expect 5 {send \x1a}
    expect -re ":$"
    
    # now do some stuff
    send "echo hello world\r"
    expect -re ":$"
    send "echo continuing\r"
    expect -re ":$"
    
    # and re-commence "X"
    send "fg\r"
    expect -re ":$"
    
    # and we're done
    send "exit\r"
    expect eof
    

    and running it:

    $ expect intr.exp
    spawn bash
    unset PROMPT_COMMAND; PS1=:
    $ unset PROMPT_COMMAND; PS1=:
    :sh -c 'n=1; while [ $n -lt 10 ]; do echo $n; sleep 1; let n=n+1; done'
    1
    2
    3
    4
    5
    ^Z
    [1]+  Stopped                 sh -c 'n=1; while [ $n -lt 10 ]; do echo $n; sleep 1; let n=n+1; done'
    :echo hello world
    hello world
    :echo continuing
    continuing
    :fg
    sh -c 'n=1; while [ $n -lt 10 ]; do echo $n; sleep 1; let n=n+1; done'
    6
    7
    8
    9
    :exit
    exit