【问题标题】:Why ssh fails from crontab but succedes when executed from a command line?为什么 ssh 从 crontab 失败但从命令行执行时成功?
【发布时间】:2010-10-26 13:21:52
【问题描述】:

我有一个 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 身份执行任何操作是错误的/错误的/等等 - 这不是这个问题的目的。

【问题讨论】:

  • 尝试使用 -v 而不是 -q --- 它仍然不起作用,但它会为您提供可能帮助您解决问题的诊断。
  • 谢谢戴夫! - 使用 -v 执行时,我在输出中包含了有趣的部分
  • 由于事实/问题的改变,我删除了我的答案。

标签: bash unix ssh crontab


【解决方案1】:

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

首先,我的 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 初始化脚本中的内容。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这与上面关于keychain 的答案有何不同?还是 netskink 下面的hard-coded answer
    • 它只是开箱即用,但在底层,它们的作用基本相同。
    【解决方案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
    

    【讨论】:

      【解决方案4】:

      keychain

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

      sudo apt-get install keychain
      

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

      如果没有运行ssh-agent,该程序将启动一个ssh-agent,并提供可以是sourced 的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
      

      【讨论】:

      • 我不认为涉及钥匙链可以以任何可靠的方式使这更容易。
      • @Dan-Kegel - 实际上,keychain 所做的正是下面的netskink's answer。除了这里,您不必自己编写代码。
      【解决方案5】:

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

      crond 执行命令时,它没有 ssh-agent 的访问权限,所以不能使用你的私钥。

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

      【讨论】:

      • Dave,如何列出在 ssh-agent 中注册的密钥?这将有助于实际检查该案例。
      • 尝试运行 ssh-add -l(即破折号小写-L)。
      • 嗯,很奇怪,这似乎不是真的。在我的 cron 脚本中,我在底部添加了一个简单的:ssh-agent,它似乎返回了一个有效的代理。 BUT 即使这样,我也无法使用奇怪的 crontab 进行 ssh 身份验证!我尝试了您的解决方案,但它也不起作用
      • 顺便说一句,当我在脚本中执行 whoami 时,我的用户名不是 root。
      • @apouche ssh-agent 不会返回现有代理,它会尝试设置一个新代理。
      猜你喜欢
      • 1970-01-01
      • 2011-10-03
      • 1970-01-01
      • 2020-05-14
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多