3

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.

Josh B
  • 227
  • 3
  • 6
  • You mean run a command in a remote server, run a command, and use the output on your local machine? – symlink Jun 17 '19 at 08:08
  • That is the default behavior. Opening an ssh session to a remote server _automatically_ redirects STDIN, STDOUT, and STDERR to/from that process. – Jonathan Hall Jun 17 '19 at 08:09

2 Answers2

2

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
Erki Aring
  • 2,032
  • 13
  • 15
0

The method you are using works, but I don't think you can reuse the same connection everytime. You can, however, do this using screen, tmux or nohup, but that would greatly increase the complexity of your script because you will now have to emulate keypresses/shortcuts. I'm not even sure if you can if you do directly in bash. If you want to emulate keypresses, you will have to run the script in a new x-terminal and use xdotool to emulate the keypresses.

Another method is to delegate the whole script to the SSH server by just running the script on the remote server itself:

ssh root@MachineB 'bash -s' < local_script.sh
Titulum
  • 9,928
  • 11
  • 41
  • 79