0

I have some experience using the bash, but this command here which I saw in a tutorial caught me off guard:

cat ~/.ssh/id_rsa.pub | ssh git@remote-server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" 

I know what the command does. It takes the output of the file ~/.ssh/id_rsa.pub, then sshs to a remote server, creates a new directory under user home called .ssh then creates a new file called authorized_keys and pours the contents of the id_rsa.pub into that file. What I couldn't figure out is, at which point contents of the id_rsa.pub file gets injected into the authorized keys file.

So, I know pipe (|) takes the output to its left and feeds it to the command to the right hand side of it. But normally we use cat command like this:

cat "content_to_be_added" >> file_to_be_appended 

so, if I'm not mistaken, contents of id_rsa.pub should get injected right before >> in order for this to work. So, how does this function exactly and why?

By the way, please feel free to correct my terminology. I'd also appreciate if you can tell me if this operator here >> has a specific name.

3
  • 3
    This seems to be re-inventing ssh-copy-id. Commented May 5, 2020 at 13:06
  • @Panki Only on systems that provide that tool. It's not (yet) a part of the official OpenSSH distribution. Commented May 5, 2020 at 13:09
  • >> is a redirection operator. See for example What are the shell's control and redirection operators? Commented May 5, 2020 at 13:09

2 Answers 2

6

The command

cat >> ~/.ssh/authorized_keys 

reads from standard input (since no filename was given to cat to read from) and appends to the named file. The >> redirection operator opens the target file for appending. Using > in place of >> would have truncated (emptied) the target file before writing the data.

Where does the data on standard input of that remote cat command come from? The standard input stream is inherited by cat from the remote shell. The remote shell inherits the standard input stream from ssh. The standard input for ssh comes via the pipe from the local cat command, which reads the ~/.ssh/id_rsa.pub file.


The local cat is not needed in your pipeline:

ssh git@remote-server 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub 

Note, however, that if mkdir does actually create a directory, that directory needs to have the correct permissions for ssh to work properly:

ssh git@remote-server 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub 

Or, you may just choose to fail to append the data:

ssh git@remote-server 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub 
3
  • Thanks a lot. So, if I execute this: cat "yeah" | ssh git@remote-server "echo", would I read "yeah" on my remote stdout? Commented May 5, 2020 at 13:32
  • 2
    echo yeah | ssh user@remote-server cat would do that - it's cat that reads from standard input, not echo. Commented May 5, 2020 at 13:36
  • 1
    @SercioSoydanov: cat "yeah" would output the content of the "yeah" file (if existing). Commented May 5, 2020 at 13:50
0

For cat, if no filename is given, it shall copy stdin to stdout.

The >> is called output redirection operator.

Simply cat >> filename will append data coming on the standard input to the file "filename".

In your example: cat "content_to_be_added" the "content_to_be_added" is not really a content, it is the name of the input file.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.