I have a bash script that does ssh to a remote machine and executes a command there, like:
ssh -nxv user@remotehost echo "hello world"
When I execute the command from a command line it works fine, but it fails when is being executed as a part of crontab (errorcode=255 - cannot establish SSH connection). Details:
... Waiting for server public key. Received server public key and host key. Host 'remotehost' is known and matches the XXX host key. ... Remote: Your host key cannot be verified: unknown or invalid host key. Server refused our host key. Trying XXX authentication with key '...' Server refused our key. ...
When executing locally I'm acting as a root, crontab works as root as well. Executing 'id' from crontab and command line gives exactly the same result:
$ id > uid=0(root) gid=0(root) groups=0(root),...
I do ssh from some local machine to the machine running crond. I have ssh key and credentials to ssh to crond machine and any other machine that the scripts connects to.
PS. Please do not ask/complain/comment that executing anything as root is bad/wrong/etc - it is not the purpose of this question.
One of the most frequent causes for the crontab job not being correctly executed is that a cronjob does not run under the user's shell environment. Another reason can be – not specifying the absolute path of the commands used in the script.
crontab files have to be regular files or symlinks to regular files, they must not be executable or writable for anyone else but the owner. This requirement can be overridden by using the -p option on the crond command line.
Cron Uses /bin/sh By Default, Not Bash Bash ( /bin/bash ) is a common shell on most distros, and is an implementation of sh.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With