31

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

ssh -nxv user@remotehost echo "hello world"

当我从命令行执行命令时,它工作正常,但在作为 crontab 的一部分执行时失败(错误代码 = 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 身份执行任何操作都是坏的/错误的/等等——这不是这个问题的目的。

4

5 回答 5

34

keychain

以一种无痛的方式解决了这个问题。它在 Debian/Ubuntu 的存储库中:

sudo apt-get install keychain

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

如果没有运行,该程序将启动ssh-agent,并提供可以sourced 的 shell 脚本并将当前 shell 连接到这个特定的ssh-agent.

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

keychain --nogui id_rsa

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

此外,将以下内容添加为您的最后一行.bashrc

. ~/.keychain/$HOSTNAME-sh

这将使 shell 知道从何处访问由 管理的 SSH 代理keychain。确保它.bashrc来自.profile.

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

* * * * * . ~/.keychain/$HOSTNAME-sh; your-actual-command
于 2013-08-04T08:22:38.803 回答
18

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

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

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

于 2009-05-15T17:09:31.723 回答
4

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

于 2016-08-03T17:07:58.993 回答
2

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

首先,我的 ssh 设置在我的 bash 初始化脚本中使用了以下脚本。

# 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 作业作为用户 ID davis。同样,如果您以用户 davis 运行并执行 crontab -e,它将创建一个以用户 davis 运行的 cron 作业。这可以通过以下条目进行验证:

30 *  *   *   *     /usr/bin/whoami

这将每 30 分钟将 whoami 的结果邮寄给用户 davis。(我以用户 davis 的身份执行了 crontabe -e。)

如果您尝试查看哪些键用作用户 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 初始化脚本中的内容。

于 2016-11-30T16:21:51.283 回答
-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
于 2013-03-11T16:22:12.277 回答