通过crontab使用ssh代理在ssh上执行rsync命令


18

我有一个cronjob:

0 9 * * * rsync -a mydir remote_machine:

我用“ crontab -e”安装了它。我有一个ssh-agent运行,当我执行rsync命令本身时,它没有任何用户交互或密码输入即可工作,但是cronjob失败,并显示以下消息:

Date: Wed,  9 Dec 2009 11:11:00 -0600 (CST)
From: Cron Daemon <me@my_machine.my_domain>
To: me@my_machine.my_domain
Subject: Cron <me@my_machine> rsync -a /home/me/mydir remote_machine:

Permission denied, please try again.
Permission denied, please try again.
Permission denied (publickey,gssapi-with-mic,password).
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at /SourceCache/rsync/rsync-35.2/rsync/io.c(452)
[sender=2.6.9]

为什么不起作用?我知道cronjobs以用户身份运行w /我(如果我运行'* * * * * touch / tmp / a'我拥有文件),所以我认为rsync正在使用我的私钥作为我登录...

Answers:


10

您的cron会话shell不了解ssh代理,因此无法与其交谈。

启动代理后,您可以将代理所需的信息放置在cron会话中。

例:

AGENT="ssh-agent -s"
if [ ! -d $HOME/.ssh/agent ]; then
        mkdir -p $HOME/.ssh/agent
fi
#
# Start an agent if there isn't one running already.
#
pid=`ps -u$LOGNAME | grep ssh-age | awk '{print $1}'`
if [ -z "$pid" ]; then
        $AGENT | grep -v echo > $HOME/.ssh/agent/$HOST & pid=$!
        sleep 1 # Let it fork and stuff
fi

然后将密钥添加到代理。

ssh-add $HOME/.ssh/id_dsa

现在,您的cron作业应在尝试使用ssh之前执行此操作:

#
# Get our parent to pick up the required SSH env vars.
#
. $HOME/.ssh/agent/$HOST

...之后,ssh会话应正常进行。


因此,我是否将所有代理程序的内容都放在脚本中,然后再加上rsync命令,或者可以将其放在cron在启动cronjob的外壳时自动加载的.profile或.bashrc文件中?
亚伦,

我将把代理程序内容放入运行rsync命令的脚本中。
大卫·麦金托什

3
我需要做的只是获取SSH_AUTH_SOCK和SSH_AGENT_PID env变量(我将它们放在.ssh-agent而不是.ssh / agent /中),所以我最终得到了这样的结果:“ 0 9 * * *。$ HOME / .ssh -agent && rsync -av $ HOME / mydir remote_machine:“
aaron

1
所有这些不必要的操作,请使用钥匙串
cmcginty 2011年

@cmcginty谁说钥匙扣可用,或者可以安装?
zb226

19

钥匙串就是您所需要的!只需安装它,然后在您的.bash_profile(或等效文件)中添加以下代码:

if [ -x /usr/bin/keychain ]; then
  /usr/bin/keychain --quiet --clear $HOME/.ssh/id_rsa
fi

对于config.fish(2):

if not status --is-interactive
   keychain --eval --quiet --quick $HOME/.ssh/id_rsa
end

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

. ~/.keychain/`/bin/hostname`-sh

对于鱼:

source $HOME/.keychain/(hostname)-fish

如果您的密钥有密码短语,则密钥串会询问您一次(在您重新启动计算机或杀死ssh-agent之前有效)。

注意:钥匙串还会向csh和生成代码fish,因此只需将后缀“ -sh”替换为“ -csh”或“ -fish”。


1
$ HOSTNAME不在cron环境中定义,但
除此之外

如果我使用rsa密钥,是否将钥匙串〜/ .ssh / id_dsa更改为钥匙串〜/ .ssh / id_rsa?
Katafalkas,2012年

完全是@Katafalkas!
semente 2012年

@Casey我已经更新了答案。现在与cron兼容。
semente 2012年

我为Fish添加了更好的说明。
伊利亚·林恩2015年

2

我没有足够的代表投票赞成第一个答案,但它解决了我遇到的问题。就ssh-agent而言,您可能已经在运行一个。这是一个从环境中提取SSH_AGENT_PID和SSH_AUTH_SOCK的脚本,无需任何其他东西即可在ssh-agent启动时保存。(假设您有perl)

将以下内容放入脚本中。(例如findagent.pl)

然后在您的cron脚本中添加以下行:

评估`{脚本路径} / findagent.pl`


\#!/usr/bin/perl -w
use strict;
my $agents = `ls -tr /tmp/ssh-*/*`;
my @agents;
(@agents) = split/\n/,$agents;

my $sshpid = `ps aux|grep ssh-agent|grep -v grep|awk '{print \$2}'|head -1`;
chomp($sshpid);
my @parts;
for (@agents) {
  chomp($_);
  if (!$_) { next; }
  my $agentfile = $_;
  (@parts) = split/\./,$agentfile;
  my $masterpid = `ps aux|grep $parts[1]|grep enlightenment`;
  if ($agentfile =~ m/$parts[1]/) {
    my $line1 = "SSH_AUTH_SOCK=" . $agentfile . '; export SSH_AUTH_SOCK';
    my $line2 = 'SSH_AGENT_PID=' . $sshpid . '; export SSH_AGENT_PID;';
    my $line3 = 'echo Agent pid ' . $sshpid . ';';
    print("$line1\n$line2\n$line3\n");
    last;
  } else {
    next;
  }
}

1

我想您正在使用基于密钥的身份验证对远程计算机进行身份验证。尝试以下行:

rsync -av --delete -e "ssh -i .ssh/id_rsa" mydir user@host.tld:~/backupDir

其中.ssh / id_rsa是私钥的路径。这是我用来进行备份的确切行,它对我而言总是正常运行。

最好的祝福,
费边


0

作为替代方案,我没有使用ssh代理,而是让我的脚本在调用rsync之前确实导出了RSYNC_RSH =“ ssh -i /home/user/.ssh/id_rsa” unset SSH_AGENT_PID unset SSH_AUTH_SOCK。通过将其放在RSYNC_RSH中而不是使用“ -e ...”,可以轻松地基于主机调整正在使用的id文件。

希望这会有所帮助,B


如果您的密钥上有密码短语,我认为这
不起作用
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.