Search code examples
bashexpect

Using expect on stderr (sshuttle as an example)


There is this program called sshuttle that can connects to a server and create a tunnel.

I wish to create a bash function that sequentially:

    1. opens a tunnel to a remote server (sshuttle -r myhost 0/0),
    1. performs 1 arbitrary commandline,
    1. kill -s TERM <pidOfTheAboveTunnel>.

A basic idea (that works but the 5 seconds delay is a problem) is like sshuttle -r myhost 0/0 & ; sleep 5 ; mycommand ; kill -s TERM $(pgrep sshuttle)

Could expect be used to expect the string "c : Connected to server." that is received from stderr here? My attempts as a newbie were met with nothing but failure, and the man page is quite impressive.


Solution

  • When you use expect to control another program, it connects to that program through a pseudo-terminal (pty), so expect sees the same output from the program as you would on a terminal, in particular there is no distinction between stdout and stderr. Assuming that your mycommand is to be executed on the local machine, you could use something like this as an expect (not bash) script:

    #!/usr/bin/expect
    
    spawn sshuttle -r myhost 0/0
    expect "Connected to server."
    exec mycommand
    exec kill [exp_pid]
    close
    

    The exec kill may not be needed if sshuttle exits when its stdin is closed, which will happen on the next line.