Search code examples
bashpipecoproc

Bash: Mutual interaction of processes via pipes


ENVIRONMENT: Linux/Docker, bash version 4.2.

QUESTION:

  • server-app accepts commands with an interactive shell.
  • server-app receives commands originating from a client.sh through a pipe.
  • server-app writes to the standard output received by client.sh.
  • client.sh considers server-app's output to determine further commands.
  • server-app might also ask for a password => That is, the terminal's standard input must be forwarded to server-app along with the output of client.sh.

I tried multiple setups with coproc. However, I either run into a stalled situation or data has not been received. How can such a setup as, shown below, be implemented in bash?

                       .------>------------------------.
     .---------.       |         .------------.  stdin |       .-----------.
     | user    |-------'         | server-app |<-------+-------| client.sh |
     | console |<--+-------------|            |     .--------->|           |
     '---------'   |      stdout '------------'     |          '-----------'
                   '--------------------------------'

MY TRY:

coproc server.app

function expect { local expectation=$1
        # read from pipe until $expectation occurs in the input stream
        # when found, echo the line to 'stdout'
        echo "EXPECT: '$expectation'"
        while true; do
            read text <&"${COPROC[0]}"
            if [[ "$text" == *"$expectation"* ]]; then
                    echo $text 
                    break
            fi
        done
}

function send { local command=$1
        # send $command through pipe 
        echo "SEND: $command"
        echo "$command" >&"${COPROC[1]}"

}


expect "Conected to URL" 
send   "open"
expect "Session keepalive"
send   "session open"

# use the reported session identifier to setup the user command
session_n=$(expect "Identifier of Session created" | cut -d' ' -f5)    
command=$(echo "$user_command" | sed -e "s/SESSION/$session_n/g")

The last three lines only demonstrate a possible processing of the server-app's output. Again what is wrong with that? How can it be brought to work.


Solution

  • As metioned by @sexpect the 'natural' way is to solve the problem is expect. This tool takes a Tcl-based script as input.

     spawn server-app
    

    would start the server-app under control of expect. expect is also a keyword in these scritps.

     expect -re "something (..)"
    

    waits for output matching the expression something (..).

     send ...
    

    sends some characters to the application.

    expect_tty ...
    

    takes some input from the user that launched the expect script.