There are many online resources about using SSH keys to achieve passwordless, cron-initiated tasks like rsyncing some files around. Most of these assume your SSH key is either not encrypted with a password, or that you're running the related command in an interactive session.
What I couldn't easily find recently was a way to make sure that a script initiated via cron on OS X 10.10 (Yosemite) and that uses an SSH key that is encrypted with a password would have access to that key as managed by the current login session's ssh-agent
.
This problem manifested itself with the following kind of output from my rsync command - being used to back up some files from a remote server - when it was executed via cron:
Permission denied, please try again. Permission denied, please try again. Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password). rsync: connection unexpectedly closed (0 bytes received so far) [receiver] rsync error: unexplained error (code 255) at /SourceCache/rsync/rsync-45/rsync/io.c(453) [receiver=2.6.9]
If I ran the same command from the shell prompt it worked fine.
This is because the shell knew about the existence of OS X's ssh-agent
and could check with it about getting access to the SSH key, without having to re-enter the password. This happens via the SSH_AUTH_SOCK
environment variable.
So, to make sure my script containing the rsync command has that same access to ssh-agent
, I added this to the top:
#!/bin/sh # Where ssh-agent is running, for password-less access to the key export SSH_AUTH_SOCK=$( ls /private/tmp/com.apple.launchd.*/Listeners ) # Now try to sync the files via SSH rsync ...
This finds the Unix socket file that ssh-agent
is using for inter-process communication and sets the environment variable with that path. When my rsync command runs a few lines later, it will be able to talk to ssh-agent
and use the encrypted SSH key. Apparently Apple changed the location of this socket file from past versions of OS X, which is why some of the other tutorials I found weren't current.
I hope and suspect this would stop working if you boot the OS X system but don't ever login. That's good for security (you don't want your SSH key to be available without some kind of intentional unlocking) but perhaps bad for consistent cron results.
Note that if you had a number of scripts firing from cron that make use of SSH, you could bring this variable into cron's environment and not clutter your scripts with setting it each time. I leave that as an exercise for the reader; if you implement that or have more efficient ways to achieve the above, please share in the comments.
Outstanding post Chris! Thanks a lot. This plus chmod +x the shell script... 🙂
Thank you so much for this tip 🙂
Thank you, exactly what I needed. Googled "mac cron rsync ssh key", yours was the first hit.
thanks! big help.
awesome, for 10.9.5 mavericks, it's
ls /private/tmp/launch-*/Listeners