Выполните команду rsync над ssh с помощью агента ssh через crontab


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 запускаются со мной как пользователь (если я запускаю '* * * * * touch / tmp / a', у меня есть файл), поэтому я предполагаю, что rsync входит как я, используя свой закрытый ключ ...

Ответы:


10

Ваша оболочка cron не знает агента 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, или я могу поместить это в какой-то файл .profile или .bashrc, который cron загружается автоматически при запуске оболочки для cronjob?
Аарон

Я бы добавил агент в скрипт, который запускает команду rsync.
Дэвид Макинтош

3
все, что мне было нужно, это получить переменные env SSH_AUTH_SOCK и SSH_AGENT_PID (я поместил их в .ssh-agent вместо .ssh / agent /), так что я закончил так: «0 9 * * *. $ HOME / .ssh -agent && rsync -av $ HOME / mydir remote_machine: "
aaron

1
Все это ненужно, используйте
связку

@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, но кроме этого это лучшее решение
cmcginty

если я использую ключи RSA, могу ли я заменить цепочку для ключей ~ / .ssh / id_dsa на цепочку для ключей ~ / .ssh / id_rsa?
Катафалкас

@ Катафалка точно!
Семен

@Casey Я обновил свой ответ. Теперь совместим с cron.
Семен

Я добавил лучшие инструкции для Рыбы.
Элайджа Линн

2

У меня недостаточно представителя, чтобы проголосовать за первый ответ, но это решило проблему, с которой я столкнулся. С точки зрения ssh-agent у вас уже может быть один запущенный. Вот скрипт для извлечения SSH_AGENT_PID & SSH_AUTH_SOCK из среды без каких-либо дополнительных вещей, чтобы сэкономить при запуске ssh-agent. (Предполагается, что у вас есть Perl)

Поместите следующее в сценарий. (например, findagent.pl)

и внутри вашего cron-скрипта добавьте строку:

eval `{путь к сценарию} / 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_RSH = "ssh -i /home/user/.ssh/id_rsa" unset SSH_AGENT_PID unset SSH_AUTH_SOCK перед вызовом rsync. Поместив его в RSYNC_RSH вместо '-e ...', вы упростили настройку используемого id-файла в зависимости от хоста.

Надеюсь, это поможет, B


Я не думаю, что это работает, если у вас есть ключевая фраза на вашем ключе
cmcginty
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.