2

My question is mostly based on this https://stackoverflow.com/questions/22479631/pipe-timely-commands-to-ssh?rq=1

I am following above question and I am able to connect to a server, like this:

mkfifo CMDs.txt
exec 7> CMDs.txt

then from another terminal I am connecting to server like this:

sshpass -p 'mypass' ssh -tt myuser@${IP} < CMDs.txt 

the session gets established, but it is not an interactive session (as it should be). But I am able to send commands to remote server by redirecting them to file descriptor 7 like:

echo "some command" >&7 
echo "some more command" >&7 

this works fine and shows the output in the other terminal on which I initiated the session. My target is to send the commands, and capture the output of each command in a variable so that I can analyze it before sending another command. I think it should be possible by reading the stdout but I am not able to figure it out, hence posting the question. I am able to capture the output in a file by redirecting it in a file like this:

sshpass -p 'mypass' ssh -tt myuser@${IP} < CMDs.txt >>outfile.txt

also as mentioned in the reference question, exec 7>&- should terminate the session, but it didn't, so how to terminate the session after I send all my commands?

Ibraheem
  • 23
  • 6

1 Answers1

4

This was a fun one (and incredibly useful!) to noodle on. In the land of input/output redirection, there is much flexibility, and thereby several options, but here's what worked for me.

First, truly, use ssh-keygen to create a private/public key pair, and install the public key on the remote server authorized_keys file (this is trivial, enhances security, and there are numerous guides online for doing this). For extra credit, password protect it, and use ssh-agent & ssh-add -- you really only have to run ssh-agent & ssh-add once per boot, and after that you're all set.

Regardless, I use the 7 file descriptor as you did, and based my FIFO names on 7, so I'll easily remember which FD I need to redirect to. ;)

# fd=7
# server=[whatever_your_server_name_is]
# mkfifo $server.$fd.in $server.$fd.out
# [ssh-agent if needed]
# ssh -tt $server <$server.$fd.in >$server.$fd.out &
# exec 7>$server.$fd.in

Now the stage is set. I could attach some script/process to $server.$fd.out, but in the following example, I just spin up cat as a listener -- for better readability, I spun this up in a separate ssh session, but that isn't strictly necessary if using an '&' to background it:

# cat $server.$fd.out

Then, whatever arbitrary commands you want:

# echo "hostname" >&7
# echo "date" >&7
# echo -e '\003' >&7  # ctrl+c...you're welcome ;)

You'll see the output. Note, first thing, you'll get the initial login motd/banner/etc, so whatever scripting/app you have attached to the output FIFO will need to be able to handle that.

It is worth noting that it is highly likely that a single FIFO could be used for both read & write, but the x.input/output worked better for my personal purposes, so that's what I show here.

FYI: Many many thanks for "getting me there". I've been trying to figure out how to have a "fast" ssh RPC, where I establish a long running ssh session, and then can later run arbitrary commands without the overhead of ssh authentication at each command -- I always string together as many commands as I can to reduce overhead (even sending small scriptlettes to read output and issue appropriate subsequent commands), but the bottom line is that when wanting to issue a quick command, it will always take several seconds of overhead for ssh to connect and authenticate (using keys, of course ;) ), and those seconds can be painful when wanting to quickly fetch something from several devices. Some rudimentary logic to handle ssh or the host going out to lunch, and re-establishing automatically, and I've got a pretty decent setup to manage my infrastructure.

The insights from your question actually filled in the missing blanks I needed to build what I needed. Hopefully this answer was able to help you too! :)

DotA
  • 56
  • 3
  • ugh...now I have no problem finding good answers -- all in the search terms! go here (ssh ControlMaster, and a better fd redirect primer): https://unix.stackexchange.com/questions/552723/store-a-remote-ssh-session/ – DotA Jan 08 '20 at 00:11