39

我编写了一个简单的脚本,它每晚将 svn 活动日志邮寄给我们的开发人员。到目前为止,我已经在 svn 存储库所在的同一台机器上运行它,所以我不必担心身份验证,我可以使用 svn 的 file:/// 地址样式。

现在我在家用计算机上运行脚本,访问远程存储库,所以我不得不更改为 svn+ssh:// 路径。设置好 ssh-key 后,在正常情况下,我无需输入密码即可访问 svn 存储库。

但是,crontab 无法访问我的 ssh-keys / ssh-agent。我在网上的几个地方读到过这个问题,这里也提到了这个问题,但没有解决:

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

我的解决方案是将其添加到脚本的顶部:

### TOTAL HACK TO MAKE SSH-KEYS WORK  ###
eval `ssh-agent -s`

这似乎在 MacOSX 10.6 下工作。

我的问题是,这有多可怕,有没有更好的方法?

4

11 回答 11

37

此外...

如果您的密钥有密码,钥匙串会询问您一次(在您重新启动机器或终止 ssh-agent 之前有效)。

钥匙扣是你需要的!只需安装它并在您的 .bash_profile 中添加以下代码:

keychain ~/.ssh/id_dsa

所以在你的脚本中使用下面的代码来加载 ssh-agent 环境变量:

. ~/.keychain/$HOSTNAME-sh

注意:keychain 还会生成 csh 和 fish shell 的代码。

从https://serverfault.com/questions/92683/execute-rsync-command-over-ssh-with-an-ssh-agent-via-crontab复制的答案

于 2011-08-02T18:58:56.967 回答
23

当您运行 ssh-agent -s 时,它会启动一个后台进程,您稍后需要终止该进程。因此,最低限度是将您的 hack 更改为:

eval `ssh-agent -s` 
svn stuff
kill $SSH_AGENT_PID

但是,我不明白这个黑客是如何工作的。简单地运行代理而不运行 ssh-add 将不会加载任何密钥。也许 MacOS 的 ssh-agent 的行为与其手册页所说的不同。

于 2010-02-05T17:25:28.430 回答
10

我有一个类似的问题。我的脚本(依赖于 ssh 密钥)在我手动运行时工作,但在使用 crontab 运行时失败。

手动定义适当的键

ssh -i /path/to/key

没用。

但最终我发现 crontab 运行 SSH 时 SSH_AUTH_SOCK 是空的。我不完全确定为什么,但我只是

env | grep SSH

复制返回的值并将此定义添加到我的 crontab 的头部。

SSH_AUTH_SOCK="/tmp/value-you-get-from-above-command"

我对这里发生的事情没有深入了解,但它解决了我的问题。crontab 现在运行顺利。

于 2011-04-28T18:32:09.370 回答
7

我的解决方案 - 基于 pra's - 即使在脚本失败时也略微改进了终止进程:

eval `ssh-agent`
function cleanup {
    /bin/kill $SSH_AGENT_PID
}
trap cleanup EXIT
ssh-add
svn-stuff

请注意,我必须在我的机器上调用 ssh-add (scientific linux 6)。

于 2013-05-22T12:43:17.927 回答
6

恢复运行 ssh-agent 的 pid 和套接字的一种方法是。

SSH_AGENT_PID=`pgrep -U $USER ssh-agent`
for PID in $SSH_AGENT_PID; do
    let "FPID = $PID - 1"
    FILE=`find /tmp -path "*ssh*" -type s -iname "agent.$FPID"`
    export SSH_AGENT_PID="$PID" 
    export SSH_AUTH_SOCK="$FILE"
done

这当然假设您在系统中安装了 pgrep,并且只有一个 ssh-agent 正在运行,或者如果有多个,它将​​采用 pgrep 最后找到的那个。

于 2011-12-12T16:58:41.063 回答
5

为了设置没有自动密码/密码破解的自动化流程,我使用了一个没有密码的单独 IdentityFile,并限制目标机器的 authorized_keys 条目以 etc. 为前缀from="automated.machine.com" ...

我为发送机器创建了一个没有密码的公私钥集:

ssh-keygen -f .ssh/id_localAuto

(提示输入密码时按回车键)

我在以下位置设置了一个 remoteAuto Host 条目.ssh/config

Host remoteAuto
    HostName remote.machine.edu
    IdentityFile  ~/.ssh/id_localAuto

和 remote.machine.edu:.ssh/authorized_keys :

...
from="192.168.1.777" ssh-rsa ABCDEFGabcdefg....
...

那么 ssh 就不需要 ssh-agent 或 keychain 提供的外部认证授权,所以你可以使用如下命令:

scp -p remoteAuto:watchdog ./watchdog_remote
rsync -Ca remoteAuto/stuff/* remote_mirror
svn svn+ssh://remoteAuto/path
svn update
... 
于 2016-02-04T15:55:17.727 回答
4

假设您已经配置了 SSH 设置并且该脚本在终端上可以正常工作,那么使用钥匙串绝对是确保脚本在 crontab 中也可以正常工作的最简单方法。

由于大多数 Unix/Linux 派生版本中不包含钥匙串,因此这里是一步一步的过程。

1.根据您的操作系统版本从http://pkgs.repoforge.org/keychain/下载适当的 rpm 包。CentOS 6 的示例:

wget http://pkgs.repoforge.org/keychain/keychain-2.7.0-1.el6.rf.noarch.rpm

2.安装包:

sudo rpm -Uvh keychain-2.7.0-1.el6.rf.noarch.rpm

3.为您的 SSH 密钥生成钥匙串文件,它们将位于 ~/.keychain 目录中。id_rsa 的示例:

keychain ~/.ssh/id_rsa

4. 在使用 SSH 身份验证的第一个命令之前的任意位置添加以下行:

source ~/.keychain/$HOSTNAME-sh

我个人试图避免为此使用其他程序,但我尝试的其他所有方法都不起作用。这工作得很好。

于 2014-02-28T04:20:52.937 回答
4

受此处其他一些答案(尤其是 vpk)的启发,我想出了以下 crontab 条目,它不需要外部脚本:

PATH=/usr/bin:/bin:/usr/sbin:/sbin

* * * * *   SSH_AUTH_SOCK=$(lsof -a -p $(pgrep ssh-agent) -U -F n | sed -n 's/^n//p') ssh hostname remote-command-here
于 2016-06-02T15:32:35.440 回答
2

如果您无法使用钥匙串并且无法从脚本启动 ssh-agent(例如,因为您的密钥受密码保护),那么这是一个可行的解决方案。

运行一次:

nohup ssh-agent > .ssh-agent-file &
. ssh-agent-file
ssh-add  # you'd enter your passphrase here

在您从 cron 运行的脚本中:

# start of script
. ${HOME}/.ssh-agent-file
# now your key is available

当然,这允许任何可以读取 '~/.ssh-agent-file' 和相应套接字的人使用您的 ssh 凭据,因此在任何多用户环境中请谨慎使用。

于 2014-05-08T15:24:05.720 回答
2

您的解决方案有效,但每次都会产生一个新的代理进程,正如其他答案所表明的那样。

我遇到了类似的问题,我发现这篇博文以及 github 上的博客中提到的 Wayne Walker 的 shell 脚本都很有用

祝你好运!

于 2016-02-23T12:50:10.607 回答
2

没有足够的声誉来评论@markshep 的答案,只是想添加一个更简单的解决方案。lsof没有为我列出套接字sudo,但find就足够了:

* * * * * SSH_AUTH_SOCK="$(find /tmp/ -type s -path '/tmp/ssh-*/agent.*' -user $(whoami) 2>/dev/null)" ssh-command

find命令在/tmp目录中搜索其完整路径名与 ssh 代理套接字文件的完整路径名匹配并由当前用户拥有的套接字。它重定向stderr/dev/null忽略许多权限被拒绝的错误,这些错误通常是find在它无权访问的目录上运行时产生的。

该解决方案假定只会为该用户找到一个套接字。

目标和路径匹配可能需要针对其他发行版/ssh 版本/配置进行修改,但应该很简单。

于 2020-04-30T07:37:14.697 回答