Виконайте команду rsync над ssh за допомогою ssh агента через crontab


18

я маю cronjob:

0 9 * * * rsync -a mydir remote_machine:

я встановив це за допомогою "crontab -e". У мене запущено ssh-агент, і коли я виконую команду 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 session немає знань про ssh-агент, тому не можете з ним спілкуватися.

Коли запускається агент, ви можете помістити інформацію, необхідну для агента, десь для початку сеансу крону.

Приклад:

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?
aaron

Я б помістив агентські речі в сценарій, який виконує команду rsync.
Девід Макінтош

3
все, що мені було потрібно, - це джерело змінних SSH_AUTH_SOCK та SSH_AGENT_PID env (я помістив їх. -agent && rsync -av $ HOME / mydir remote_machine: "
aaron

1
Все це непотрібне, використовуйте брелок
cmcginty

@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

Якщо у вашому ключі є парольна фраза, keychain попросить вас один раз (дійсний, поки ви не перезавантажите машину або не вб'єте ssh-агент).

Примітка: брелок також генерує код cshі fishоболонки, тому просто замініть суфікс «-SH» до «-csh» або «-риба».


1
$ HOSTNAME не визначено в середовищі cron, окрім того, що це найкраще рішення
cmcginty

якщо я використовую клавіші rsa, чи зміню я брелок ~ / .ssh / id_dsa на брелок ~ / .ssh / id_rsa?
Katafalkas

@Katafalkas точно!
semente

@Casey Я оновив свою відповідь. Тепер сумісний з cron.
1212

Я додав кращі інструкції для Риб.
Ілля Лінн

2

У мене недостатньо представників, щоб проголосувати першу відповідь, але це вирішило питання, яке у мене виникло. Що стосується ssh-агента, у вас вже може бути один запущений. Ось сценарій для вилучення SSH_AGENT_PID & SSH_AUTH_SOCK з навколишнього середовища без додаткових матеріалів, щоб заощадити при запуску ssh-агента. (Припустимо, що у вас є 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 ...', це дозволило легко налаштувати ідентифікаційний файл, що використовується на основі хоста.

Сподіваюся, це допомагає, Б


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