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.

AdminBee
  • 22,803

2 Answers2

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
Kusalananda
  • 333,661
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.