ssh-agent和crontab - 是否有一种很好的方式来满足这些需求?

时间:2010-02-05 05:44:01

标签: bash unix cron ssh-keys

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

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

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

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

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

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

这似乎适用于MacOSX 10.6。

我的问题是,这有多糟糕,还有更好的方法吗?

11 个答案:

答案 0 :(得分:30)

另外......

如果你的密钥有密码,密钥链会问你一次(有效直到你重启机器或杀死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

的回复

答案 1 :(得分:21)

当您运行ssh-agent -s时,它会启动后台进程,您需要稍后终止该进程。所以,最低限度是将你的黑客改为:

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

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

答案 2 :(得分:7)

我有类似的问题。我的脚本(依赖于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现在运行顺利。

答案 3 :(得分: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,或者在多个ssh-agent的情况下,它将采用pgrep最后找到的那个。

答案 4 :(得分:5)

我的解决方案 - 基于pra的 - 稍微改进了甚至在脚本失败时杀死进程:

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

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

答案 5 :(得分:4)

设置自动流程,无需自动密码/密码短语, 我使用一个没有密码的单独的IdentityFile,并限制目标机器的authorized_keys条目前缀为from="automated.machine.com" ...等。

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

ssh-keygen -f .ssh/id_localAuto

(提示输入密码短语时返回)

我在.ssh/config中设置了remoteAuto主机条目:

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

答案 6 :(得分:3)

假设您已经配置了SSH设置并且该脚本在终端上正常工作,使用 keychain 绝对是确保脚本在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

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

答案 7 :(得分:3)

受到其他一些答案的启发(特别是vpk' s),我提出了以下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

答案 8 :(得分: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凭据的相应套接字,因此在任何多用户环境中都要谨慎使用。

答案 9 :(得分:1)

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

我遇到了类似的问题,我发现这个blogpost和Wayne Walker在github的博客中提到的shell脚本一样有用。

祝你好运!

答案 10 :(得分:1)

没有足够的声誉来评论@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版本/配置,目标和路径匹配可能需要修改,但是应该很简单。