Wykonaj komendę rsync przez ssh z agentem ssh przez crontab


18

mam cronjob:

0 9 * * * rsync -a mydir remote_machine:

zainstalowałem to z 'crontab -e'. mam uruchomionego agenta ssh, a kiedy wykonuję samą komendę rsync, działa ona bez interakcji użytkownika lub hasła, ale cronjob kończy się niepowodzeniem z następującym komunikatem:

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]

dlaczego to nie działa wiem, że cronjobs działają w / me jako użytkownik (jeśli uruchamiam „* * * * * touch / tmp / a” jestem właścicielem pliku), więc zakładam, że rsync loguje się jako ja za pomocą mojego klucza prywatnego ...

Odpowiedzi:


10

Twoja powłoka sesji cron nie ma wiedzy o agencie ssh, więc nie możesz z nim rozmawiać.

Po uruchomieniu agenta możesz umieścić informacje potrzebne agentowi w miejscu, w którym ma zostać pobrana sesja cron.

Przykład:

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

Następnie dodaj swój klucz do agenta.

ssh-add $HOME/.ssh/id_dsa

Teraz twoje zadanie crona powinno to zrobić przed próbą użycia ssh:

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

... po czym sesja ssh powinna przebiegać normalnie.


więc czy mogę umieścić wszystkie rzeczy agenta w skrypcie, a następnie komendę rsync, czy mogę umieścić to w jakimś pliku .profile lub .bashrc, który cron ładuje się automatycznie, gdy uruchamia powłokę dla cronjob?
aaron,

Umieściłbym agenta w skrypcie, który uruchamia komendę rsync.
David Mackintosh,

3
wszystko, czego potrzebowałem, to źródło zmiennych env SSH_AUTH_SOCK i SSH_AGENT_PID (wstawiłem je do pliku .ssh-agent zamiast .ssh / agent /), więc to właśnie skończyłem z: „0 9 * * *. $ HOME / .ssh -agent && rsync -av $ HOME / mydir remote_machine: "
aaron

1
Wszystko to niepotrzebne, użyj pęku kluczy
cmcginty

@cmcginty, który mówi, że pęku kluczy jest dostępny, czy można go zainstalować?
zb226,

19

brelok jest tym, czego potrzebujesz! Wystarczy go zainstalować i dodać następujący kod w swoim .bash_profile(lub równoważnym):

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

Dla config.fish ( 2 ):

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

Następnie użyj poniższego kodu w skrypcie, aby załadować zmienne środowiskowe ssh-agent:

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

Dla ryb:

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

Jeśli twój klucz ma hasło, pęku kluczy zapyta Cię raz (ważne, dopóki nie uruchomisz ponownie komputera lub nie zabijesz agenta ssh).

Uwaga: pęku kluczy generuje również kod do cshi fishpowłoki, więc po prostu zamień przyrostek „-sh” na „-csh” lub „-fish”.


1
$ HOSTNAME nie jest zdefiniowany w środowisku cron, ale poza tym jest to najlepsze rozwiązanie
cmcginty,

jeśli używam kluczy rsa, czy mogę zmienić pęku kluczy ~ / .ssh / id_dsa na keychain ~ / .ssh / id_rsa?
Katafalkas

@Katafalkas dokładnie!
semente

@Casey Zaktualizowałem swoją odpowiedź. Teraz jest kompatybilny z cronem.
semente

Dodałem lepsze instrukcje dla Fisha.
Elijah Lynn

2

Nie mam wystarczającej liczby przedstawicieli, aby zagłosować za pierwszą odpowiedzią, ale rozwiązało to mój problem. Jeśli chodzi o ssh-agent, możesz już mieć jednego uruchomionego. Oto skrypt, aby wyodrębnić SSH_AGENT_PID i SSH_AUTH_SOCK ze środowiska bez żadnych dodatkowych rzeczy do zapisania przy uruchomieniu ssh-agent. (Zakłada, że ​​masz perla)

Umieść w skrypcie następujące elementy. (na przykład findagent.pl)

i wewnątrz skryptu cron dodaj wiersz:

eval `{ścieżka do skryptu} / 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

Przypuszczam, że używasz uwierzytelniania opartego na kluczach do uwierzytelniania się na zdalnym komputerze. Wypróbuj poniższą linię:

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

Gdzie .ssh / id_rsa jest ścieżką do twojego klucza prywatnego. Jest to dokładna linia, której używam do tworzenia kopii zapasowych i zawsze działa dla mnie dobrze.

Najlepsze życzenia,
Fabian


0

Alternatywnie, zamiast używać agenta ssh, zmusiłem skrypt do eksportu RSYNC_RSH = "ssh -i /home/user/.ssh/id_rsa" unset SSH_AGENT_PID unset SSH_AUTH_SOCK przed wywołaniem rsync. Umieszczając go w RSYNC_RSH zamiast używać „-e ...”, ułatwiło dostosowanie używanego pliku id na podstawie hosta.

Mam nadzieję, że to pomaga, B.


Nie sądzę, żeby to
zadziałało,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.