为什么ssh从crontab失败但在从命令行执行时成功?

时间:2009-05-15 16:12:20

标签: bash unix ssh crontab

我有一个bash脚本,它对远程机器执行ssh并在那里执行命令,如:

ssh -nxv user@remotehost echo "hello world"

当我从命令行执行命令时,它工作正常,但在作为crontab的一部分执行时失败(errorcode = 255 - 无法建立SSH连接)。详细说明:

...
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.
...

在本地执行时,我充当root用户,crontab也以root身份运行。 从crontab和命令行执行'id'会得到完全相同的结果:

$ id
> uid=0(root) gid=0(root) groups=0(root),...

我从一些本地机器ssh到运行crond的机器。我有ssh密钥和凭据ssh到crond机器和脚本连接的任何其他机器。

PS。请不要问/抱怨/评论以root身份执行任何错误/错误/等等 - 这不是这个问题的目的。

5 个答案:

答案 0 :(得分:25)

keychain

以无痛的方式解决这个问题。它在Debian / Ubuntu的回购中:

sudo apt-get install keychain

也许对于许多其他发行版(看起来它起源于Gentoo)。

如果没有正在运行,此程序将启动ssh-agent,并提供可source d的shell脚本,并将当前shell连接到此特定ssh-agent

对于bash,使用名为id_rsa的私钥,将以下内容添加到.profile

keychain --nogui id_rsa

这将启动ssh-agent并在重新启动后首次登录时添加id_rsa密钥。如果密钥受密码保护,它也会要求密码短语。 不再需要使用不受保护的密钥了!对于后续登录,它会识别代理,而不是再次要求密码。

另外,请将以下内容添加为.bashrc的最后一行:

. ~/.keychain/$HOSTNAME-sh

这将让shell知道到达keychain管理的SSH代理的位置。确保.bashrc来自.profile

但是,cron工作似乎仍然没有看到这一点。作为补救措施,请在实际命令之前的crontab中包含上述行:

* * * * * . ~/.keychain/$HOSTNAME-sh; your-actual-command

答案 1 :(得分:9)

我猜通常当你从本地机器ssh到运行crond的机器时,你的私钥被加载到ssh-agent中并通过连接转发。因此,当您从命令行执行命令时,它会在ssh-agent中找到您的私钥,并使用它来登录远程计算机。

当crond执行命令时,它无法访问ssh-agent,因此无法使用您的私钥。

您必须在运行crond的计算机上为root创建一个新的私钥,并将其公共部分复制到您希望crond登录的远程计算机上的相应authorized_keys文件中。 / p>

答案 2 :(得分:4)

不要在没有密码短语的情况下公开SSH密钥。请改用ssh-cron,这允许您使用SSH代理安排任务。

答案 3 :(得分:1)

所以我遇到了类似的问题。我来到这里并看到了各种答案,但这里有一些实验是我如何使用密码短语,ssh-agent和cron的sshkeys。

首先,我的ssh安装程序在我的bash init脚本中使用以下脚本。

# JFD Added this for ssh
SSH_ENV=$HOME/.ssh/environment

    # start the ssh-agent
    function start_agent {
        echo "Initializing new SSH agent..."
        # spawn ssh-agent
        /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
        echo succeeded
        chmod 600 "${SSH_ENV}"
        . "${SSH_ENV}" > /dev/null
        /usr/bin/ssh-add
    }


    if [ -f "${SSH_ENV}" ]; then
         . "${SSH_ENV}" > /dev/null
         ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
            start_agent;
        }
   else
        start_agent;
   fi

当我登录时,我输入一次密码,然后从那时起,它将使用ssh-agent自动验证我。

ssh-agent详细信息保存在.ssh / environment中。这是脚本的样子:

SSH_AUTH_SOCK=/tmp/ssh-v3Tbd2Hjw3n9/agent.2089; export SSH_AUTH_SOCK;
SSH_AGENT_PID=2091; export SSH_AGENT_PID;
#echo Agent pid 2091;

关于cron,您可以通过各种方式将作业设置为普通用户。 如果以root用户身份运行crontab -e,它将设置root用户cron。如果你以crontab -u davis -e运行,它将添加一个cron作为userid davis。同样,如果您以用户davis身份运行并执行crontab -e,它将创建一个以userid davis身份运行的cron作业。这可以通过以下条目进行验证:

30 *  *   *   *     /usr/bin/whoami

这将每30分钟将whoami的结果邮寄给用户davis。 (我做了一个crontabe -e作为用户davis。)

如果您尝试查看用户davis使用的键,请执行以下操作:

36 *  *   *   *     /usr/bin/ssh-add -l

它会失败,邮件发送的日志会说

To: davis@xxxx.net
Subject: Cron <davis@hostyyy> /usr/bin/ssh-add -l

Could not open a connection to your authentication agent.

解决方案是为上面的ssh-agent提供env脚本。以下是生成的cron条目:

55 10  *   *   *     . /home/davis/.ssh/environment; /home/davis/bin/domythingwhichusesgit.sh

这将在10:55运行脚本。注意领先。在脚本中。它表示在我的环境中运行此脚本,类似于.bash init脚本中的脚本。

答案 4 :(得分:-3)

昨天我遇到了类似的问题...

我在一台服务器上有cron作业,它使用ssh在其他服务器上启动一些操作...问题是用户权限和密钥......

在crontab我有

* * * * * php /path/to/script/doSomeJob.php

它根本不起作用(没有权限)。 我尝试将cron作为特定用户运行,该用户连接到其他服务器

* * * * * user php /path/to/script/doSomeJob.php

但没有效果。

最后,我导航到脚本,然后执行php文件,它工作..

* * * * * cd /path/to/script/; php doSomeJob.php