Search code examples
linuxbashfile-descriptor

How to connect input/output to SSH session


What is a good way to be able to directly send to STDIN and receive from STDOUT of a process? I'm specifically interested in SSH, as I want to do the following:

[ssh into a remote server]
[run remote commands]
[run local commands]
[run remote commands]
 etc...

For example, let's say I have a local script "localScript" that will output the next command I want to run remotely, depending on the output of "remoteScript". I could do something like:

output=$(ssh myServer "./remoteScript")
nextCommand=$(./localScript $output)
ssh myServer "$nextCommand"

But it would be nice to do this without closing/reopening the SSH connection at every step.


Solution

  • You can redirect SSH input and output to FIFO-s and then use these for two-way communication.

    For example local.sh:

    #!/bin/sh
    
    SSH_SERVER="myServer"
    
    # Redirect SSH input and output to temporary named pipes (FIFOs)
    SSH_IN=$(mktemp -u)
    SSH_OUT=$(mktemp -u)
    mkfifo "$SSH_IN" "$SSH_OUT"
    ssh "$SSH_SERVER" "./remote.sh" < "$SSH_IN" > "$SSH_OUT" &
    
    # Open the FIFO-s and clean up the files
    exec 3>"$SSH_IN"
    exec 4<"$SSH_OUT"
    rm -f "$SSH_IN" "$SSH_OUT"
    
    # Read and write
    counter=0
    echo "PING${counter}" >&3
    cat <&4 | while read line; do
        echo "Remote responded: $line"
        sleep 1
        counter=$((counter+1))
        echo "PING${counter}" >&3
    done
    

    And simple remote.sh:

    #!/bin/sh
    
    while read line; do
        echo "$line PONG"
    done