Question

I wrote a simple script which mails out svn activity logs nightly to our developers. Until now, I've run it on the same machine as the svn repository, so I didn't have to worry about authentication, I could just use svn's file:/// address style.

Now I'm running the script on a home computer, accessing a remote repository, so I had to change to svn+ssh:// paths. With ssh-key nicely set up, I don't ever have to enter passwords for accessing the svn repository under normal circumstances.

However, crontab did not have access to my ssh-keys / ssh-agent. I've read about this problem a few places on the web, and it's also alluded to here, without resolution:

Why ssh fails from crontab but succedes when executed from a command line?

My solution was to add this to the top of the script:

### TOTAL HACK TO MAKE SSH-KEYS WORK  ###
eval `ssh-agent -s`

This seems to work under MacOSX 10.6.

My question is, how terrible is this, and is there a better way?

Was it helpful?

Solution

When you run ssh-agent -s, it launches a background process that you'll need to kill later. So, the minimum is to change your hack to something like:

eval `ssh-agent -s` 
svn stuff
kill $SSH_AGENT_PID

However, I don't understand how this hack is working. Simply running an agent without also running ssh-add will not load any keys. Perhaps MacOS' ssh-agent is behaving differently than its manual page says it does.

OTHER TIPS

In addition...

If your key have a passhphrase, keychain will ask you once (valid until you reboot the machine or kill the ssh-agent).

keychain is what you need! Just install it and add the follow code in your .bash_profile:

keychain ~/.ssh/id_dsa

So use the code below in your script to load the ssh-agent environment variables:

. ~/.keychain/$HOSTNAME-sh

Note: keychain also generates code to csh and fish shells.

Copied answer from https://serverfault.com/questions/92683/execute-rsync-command-over-ssh-with-an-ssh-agent-via-crontab

I had a similar problem. My script (that relied upon ssh keys) worked when I ran it manually but failed when run with crontab.

Manually defining the appropriate key with

ssh -i /path/to/key

didn't work.

But eventually I found out that the SSH_AUTH_SOCK was empty when the crontab was running SSH. I wasn't exactly sure why, but I just

env | grep SSH

copied the returned value and added this definition to the head of my crontab.

SSH_AUTH_SOCK="/tmp/value-you-get-from-above-command"

I'm out of depth as to what's happening here, but it fixed my problem. The crontab runs smoothly now.

One way to recover the pid and socket of running ssh-agent would be.

SSH_AGENT_PID=`pgrep -U $USER ssh-agent`
for PID in $SSH_AGENT_PID; do
    let "FPID = $PID - 1"
    FILE=`find /tmp -path "*ssh*" -type s -iname "agent.$FPID"`
    export SSH_AGENT_PID="$PID" 
    export SSH_AUTH_SOCK="$FILE"
done

This of course presumes that you have pgrep installed in the system and there is only one ssh-agent running or in case of multiple ones it will take the one which pgrep finds last.

My solution - based on pra's - slightly improved to kill process even on script failure:

eval `ssh-agent`
function cleanup {
    /bin/kill $SSH_AGENT_PID
}
trap cleanup EXIT
ssh-add
svn-stuff

Note that I must call ssh-add on my machine (scientific linux 6).

Assuming that you already configured SSH settings and that script works fine from terminal, using the keychain is definitely the easiest way to ensure that script works fine in crontab as well.

Since keychain is not included in most of Unix/Linux derivations, here is the step by step procedure.

1. Download the appropriate rpm package depending on your OS version from http://pkgs.repoforge.org/keychain/. Example for CentOS 6:

wget http://pkgs.repoforge.org/keychain/keychain-2.7.0-1.el6.rf.noarch.rpm

2. Install the package:

sudo rpm -Uvh keychain-2.7.0-1.el6.rf.noarch.rpm

3. Generate keychain files for your SSH key, they will be located in ~/.keychain directory. Example for id_rsa:

keychain ~/.ssh/id_rsa

4. Add the following line to your script anywhere before the first command that is using SSH authentication:

source ~/.keychain/$HOSTNAME-sh

I personally tried to avoid to use additional programs for this, but everything else I tried didn't work. And this worked just fine.

To set up automated processes without automated password/passphrase hacks, I use a separate IdentityFile that has no passphrase, and restrict the target machines' authorized_keys entries prefixed with from="automated.machine.com" ... etc..

I created a public-private keyset for the sending machine without a passphrase:

ssh-keygen -f .ssh/id_localAuto

(Hit return when prompted for a passphrase)

I set up a remoteAuto Host entry in .ssh/config:

Host remoteAuto
    HostName remote.machine.edu
    IdentityFile  ~/.ssh/id_localAuto

and the remote.machine.edu:.ssh/authorized_keys with:

...
from="192.168.1.777" ssh-rsa ABCDEFGabcdefg....
...

Then ssh doesn't need the externally authenticated authorization provided by ssh-agent or keychain, so you can use commands like:

scp -p remoteAuto:watchdog ./watchdog_remote
rsync -Ca remoteAuto/stuff/* remote_mirror
svn svn+ssh://remoteAuto/path
svn update
... 

Inspired by some of the other answers here (particularly vpk's) I came up with the following crontab entry, which doesn't require an external script:

PATH=/usr/bin:/bin:/usr/sbin:/sbin

* * * * *   SSH_AUTH_SOCK=$(lsof -a -p $(pgrep ssh-agent) -U -F n | sed -n 's/^n//p') ssh hostname remote-command-here

Here is a solution that will work if you can't use keychain and if you can't start an ssh-agent from your script (for example, because your key is passphrase-protected).

Run this once:

nohup ssh-agent > .ssh-agent-file &
. ssh-agent-file
ssh-add  # you'd enter your passphrase here

In the script you are running from cron:

# start of script
. ${HOME}/.ssh-agent-file
# now your key is available

Of course this allows anyone who can read '~/.ssh-agent-file' and the corresponding socket to use your ssh credentials, so use with caution in any multi-user environment.

Your solution works but it will spawn a new agent process every time as already indicated by some other answer.

I faced similar issues and I found this blogpost useful as well as the shell script by Wayne Walker mentioned in the blog on github.

Good luck!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top