Working with ssh

This post contains a few quick and useful facts about using ssh from OS X’s terminal.

ssh is an extraordinarily useful shell tool for logging in to, and getting a shell on a remote machine. You generally use it like this:

$ ssh

At which point, you’re prompted for a password. Which brings me to my first useful tip.

Skipping password entry

It turns out that you don’t have to type your password every time you use ssh if you’re always talking to the same remote host. You can do this securely by setting up a public/private key pair on your machine, and then giving your public key to the remote machine. After setting this up, the remote machine can confirm that ssh-using party knows your private key, without you having to type anything.

There are two big steps to accomplish this: (1) make sure you have a public/private key pair, which may already be done for you; and then (2) let the remote machine know about your public key.

Make sure you have keys

You might already have a public/private key pair, in which case you can skip this step. Check to see if you already have them:

$ cd ~/.ssh
# If it says "no such file or directory", then you need to generate a key pair; otherwise:
$ ls
# If you see files named "id_rsa" and "", you're all good.

If you need to generate a key pair, execute this command:

$ ssh-keygen -t rsa -C ""

You might need to hit enter once or twice to get that command to complete – no passphrase is fine, the default settings are fine. Associating your email address with a key is optional, but can be useful to you or others for knowing which user is associated with this public key.

Letting the remote know your public key

If your remote account is set up correctly, executing this one-liner from your local .ssh directory will finish everything up for you:

$ scp <user>@<yourhost>:.ssh/authorized_keys

If you don’t see any error message after that, it succeeded! Good work. Buy yourself a fancy drink. And one for me, while you’re at it, I’m thirsty here.

If it doesn’t work, ssh in to the remote machine, and make sure the .ssh directory exists. If not, create it, and try to send the file again (same scp line as before). If you’ve created the directory, and have permission to write to it, that should work. Anytime you ssh into that machine from now on, it won’t ask you for your password. Nice!

(Edit: Commenter @Adam helpfully pointed out that there’s a more official way to do this, using the ssh-copy-id command (ref). Unfortunately, this command is not installed by default, but can be obtained by installing homebrew and typing brew install ssh-copy-id. The scp command I give above is sort of a brutish, simplified version of that. Thanks for the tip!)

Dealing with a broken connection

For some strange reason, if you’re using ssh and the connection is broken, it basically seems as if your terminal is frozen. It just doesn’t respond to commands. But there is a way out. Just hit the enter, tilde, and period keys, in that order (tilde = shift+back-quote of course).

Why does that work? You can read more about this in the man ssh pages, under escape characters. Or, within ssh, hit enter, tilde, question-mark, to see a quick summary of what other meta-commands are available.

There’s also a way to address this problem more preemptively. You can edit ssh’s config file, setting the ServerAliveInterval to 10, or any positive number (I recommend something close to 10, though). This value indicates the number of seconds without hearing anything from the server before an encrypted ping is sent to check that the connection is still alive. The default value is 0, which means no such pings are ever sent. Here’s the details of how to set this up:

$ cd ~/.ssh
$ vim config
# Hit the i key to enter insert mode, and type the following line:
ServerAliveInterval 10
# Hit escape, then type:
# and hit enter, which saves the file and exits vim.

To read more about ssh config options, type man ssh_config from your bash prompt.

Syncing with server code

The last thing I want to mention is a bash script I use for keeping my local machine’s git repository synchronized with my server code. If you have a lot of server code, it might make sense to use a dedicated git repository for that code. I’m talking about a different situation – I have a lot of iOS code, and there’s about 200 lines of php code I need to run a very simple server. In this case, I’d rather have a single git repo on my machine, and keep a copy of the php files on my server. I use sftp to keep the files synchronized. The above scp command that eliminates the need for passwords in ssh also works for sftp, so it becomes easier to use sftp from a bash script.

Here’s a copy of a script that pulls in all php files from a given remote directory, into the current directory:

sftp <user>@<yourhost>:<subdir> <<EOF
get *.php

I hope that’s helpful!