Execute o comando rsync sobre ssh com um agente ssh via crontab


18

Eu tenho um cronjob:

0 9 * * * rsync -a mydir remote_machine:

Eu instalei isso com 'crontab -e'. Eu tenho um agente ssh em execução e, quando executo o próprio comando rsync, ele funciona sem qualquer interação do usuário ou entrada de senha, mas o cronjob falha com a seguinte mensagem:

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]

por que isso não funciona? Eu sei que os cronjobs executam w / me como usuário (se eu executar '* * * * * touch / tmp / a' eu possuo o arquivo), por isso presumo que o rsync esteja efetuando login como eu usando minha chave privada ...

Respostas:


10

Seu shell de sessão cron não tem conhecimento do agente ssh, portanto não pode falar com ele.

Quando o agente é iniciado, você pode colocar as informações necessárias para o agente em algum lugar da sessão cron.

Exemplo:

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

Em seguida, adicione sua chave ao agente.

ssh-add $HOME/.ssh/id_dsa

Agora seu trabalho cron deve fazer isso antes de tentar usar o ssh:

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

... após o qual, a sessão ssh deve prosseguir normalmente.


coloquei todas as coisas do agente em um script seguido pelo comando rsync ou posso colocá-lo em algum arquivo .profile ou .bashrc que o cron carrega automaticamente quando inicia um shell para um cronjob?
aaron

Eu colocaria as coisas do agente no script que executa o comando rsync.
David Mackintosh

3
tudo o que eu precisava era criar as variáveis ​​env SSH_AUTH_SOCK e SSH_AGENT_PID (eu as coloquei em .ssh-agent em vez de .ssh / agent /), então foi isso que eu acabei com: "0 9 * * *. $ HOME / .ssh -agent && rsync -av $ HOME / mydir remote_machine: "
aaron

11
Tudo isso desnecessário, uso chaveiro
cmcginty

@cmcginty quem disse que o chaveiro está disponível ou pode ser instalado?
zb226

19

chaveiro é o que você precisa! Basta instalá-lo e adicionar o código a seguir no seu .bash_profile(ou equivalente):

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

Para config.fish ( 2 ):

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

Em seguida, use o código abaixo no seu script para carregar as variáveis ​​de ambiente do ssh-agent:

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

Para peixes:

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

Se sua chave tiver uma frase secreta, a chave solicitará uma vez (válida até você reiniciar a máquina ou matar o ssh-agent).

Nota: o chaveiro também gera código para cshe fishconchas, portanto, substitua o sufixo "-sh" por "-csh" ou "-fish".


11
$ HOSTNAME não está definido no ambiente cron, mas diferente do que esta é a melhor solução
cmcginty

se eu usar chaves rsa, altero keychain ~ / .ssh / id_dsa para keychain ~ / .ssh / id_rsa?
Katafalkas

@Katafalkas exatamente!
semente

@ Casey Atualizei minha resposta. Agora é compatível com cron.
22/08/12

Eu adicionei melhores instruções para peixes.
Elias Lynn

2

Não tenho representante suficiente para votar na primeira resposta, mas resolveu o problema que estava tendo. Em termos de ssh-agent, você já pode ter um em execução. Aqui está um script para extrair o SSH_AGENT_PID & SSH_AUTH_SOCK do ambiente sem nenhum material adicional a ser salvo na inicialização do ssh-agent. (Supõe que você tenha perl)

Coloque o seguinte em um script. (por exemplo, findagent.pl)

e dentro do seu script cron, adicione a linha:

eval `{caminho para o script} / 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

Suponho que você esteja usando autenticação baseada em chave para se autenticar na máquina remota. Experimente a linha abaixo:

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

Onde .ssh / id_rsa é o caminho para sua chave privada. Esta é a linha exata que estou usando para fazer meus backups e sempre funciona bem para mim.

Muitas felicidades,
Fabian


0

Como alternativa, em vez de usar o agente ssh, fiz o meu script exportar RSYNC_RSH = "ssh -i /home/user/.ssh/id_rsa" unset SSH_AGENT_PID não SSH_AUTH_SOCK antes de chamar o rsync. Ao colocá-lo em RSYNC_RSH, em vez de usar '-e ...', foi fácil ajustar o arquivo de identificação usado com base no host.

Espero que isso ajude, B


Eu não acho que isso funciona se você tiver uma senha em sua chave
cmcginty
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.