Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 303
tkokoszka Avatar asked May 15 '09 16:05

tkokoszka


People also ask

Why crontab scripts are not working?

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.

Does crontab need to be executable?

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.

What Shell is crontab using?

Cron Uses /bin/sh By Default, Not Bash Bash ( /bin/bash ) is a common shell on most distros, and is an implementation of sh.


1 Answers

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 sourced 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 
like image 83
krlmlr Avatar answered Oct 24 '22 06:10

krlmlr