Why ssh fails from crontab but succedes when executed from a command line?
keychain
solves this in a painless way. It's in the repos for Debian/Ubuntu:
sudo apt-get install keychain
and perhaps for many other distros (it looks like it originated from Gentoo).
This program will start an ssh-agent
if none is running, and provide shell scripts that can be source
d and connect the current shell to this particular ssh-agent
.
For bash
, with a private key named id_rsa
, add the following to your .profile
:
keychain --nogui id_rsa
This will start an ssh-agent
and add the id_rsa
key on the first login after reboot. If the key is passphrase-protected, it will also ask for the passphrase. No need to use unprotected keys anymore! For subsequent logins, it will recognize the agent and not ask for a passphrase again.
Also, add the following as a last line of your .bashrc
:
. ~/.keychain/$HOSTNAME-sh
This will let the shell know where to reach the SSH agent managed by keychain
. Make sure that .bashrc
is sourced from .profile
.
However, it seems that cron
jobs still don't see this. As a remedy, include the line above in the crontab
, just before your actual command:
* * * * * . ~/.keychain/$HOSTNAME-sh; your-actual-command
I am guessing that normally when you ssh from your local machine to the machine running crond, your private key is loaded in ssh-agent and forwarded over the connection. So when you execute the command from the command line, it finds your private key in ssh-agent and uses it to log in to the remote machine.
When crond executes the command, it does not have access to ssh-agent, so cannot use your private key.
You will have to create a new private key for root on the machine running crond, and copy the public part of it to the appropriate authorized_keys
file on the remote machine that you want crond to log in to.