Ejecute el comando rsync sobre ssh con un agente ssh a través de crontab

18

tengo un cronjob:

0 9 * * * rsync -a mydir remote_machine:

Lo instalé con 'crontab -e'. Tengo un agente ssh ejecutándose, y cuando ejecuto el comando rsync en sí mismo, funciona sin ninguna interacción del usuario o entrada de contraseña, pero el cronjob falla con el siguiente mensaje:

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 qué no funciona esto? Sé que los cronjobs se ejecutan conmigo como el usuario (si ejecuto '* * * * * touch / tmp / a' soy dueño del archivo), así que supongo que rsync inicia sesión como yo usando mi clave privada ...

aaron
fuente

Respuestas:

10

Su shell de sesión cron no tiene conocimiento del agente ssh, por lo que no puede hablar con él.

Cuando se inicia el agente, puede colocar la información necesaria para el agente en algún lugar para que la sesión cron se recupere.

Ejemplo:

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

Luego agregue su clave al agente.

ssh-add $HOME/.ssh/id_dsa

Ahora su trabajo cron debería hacer esto antes de intentar usar ssh:

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

... después de lo cual, la sesión ssh debería continuar normalmente.

David Mackintosh
fuente
entonces, ¿pongo todas las cosas del agente en un script seguido del comando rsync, o puedo ponerlo en algún archivo .profile o .bashrc que cron carga automáticamente cuando inicia un shell para un cronjob?
aaron
Pondría las cosas del agente en el script que ejecuta el comando rsync.
David Mackintosh
3
todo lo que necesitaba era obtener las variables env SSH_AUTH_SOCK y SSH_AGENT_PID (las puse en .ssh-agent en lugar de .ssh / agent /) así que esto fue lo que terminé con: "0 9 * * *. $ HOME / .ssh -agent && rsync -av $ HOME / mydir remote_machine: "
aaron
1
Todo esto innecesario, use llavero
cmcginty
@cmcginty, ¿quién dice que el llavero está disponible o se puede instalar?
zb226
19

llavero es lo que necesitas! Simplemente instálelo y agregue el siguiente código en su .bash_profile(o 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

Luego use el siguiente código en su script para cargar las variables de entorno ssh-agent:

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

Para peces:

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

Si su clave tiene una frase de contraseña, el llavero le preguntará una vez (válido hasta que reinicie la máquina o elimine el agente ssh).

Nota: el llavero también genera código cshy fishshells, así que simplemente reemplace el sufijo "-sh" por "-csh" o "-fish".

semente
fuente
1
$ HOSTNAME no está definido en el entorno cron, pero aparte de eso, esta es la mejor solución
cmcginty
si uso las teclas rsa, ¿cambio el llavero ~ / .ssh / id_dsa por el llavero ~ / .ssh / id_rsa?
Katafalkas
@Katafalkas exactamente!
semente
@Casey He actualizado mi respuesta. Ahora es compatible con cron.
semente
Agregué mejores instrucciones para Fish.
Elijah Lynn
2

No tengo suficiente representante para votar la primera respuesta, pero resolvió el problema que estaba teniendo. En términos de ssh-agent, es posible que ya tenga uno en ejecución. Aquí hay un script para extraer el SSH_AGENT_PID y SSH_AUTH_SOCK del entorno sin ningún material adicional para guardar en el inicio de ssh-agent. (Asume que tienes perl)

Ponga lo siguiente en un script. (por ejemplo findagent.pl)

y dentro de su secuencia de comandos cron agregue la línea:

eval `{ruta de acceso al 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;
  }
}
mutsu
fuente
1

Supongo que está utilizando autenticación basada en clave para autenticarse con la máquina remota. Prueba la siguiente línea:

rsync -av --delete -e "ssh -i .ssh/id_rsa" mydir [email protected]:~/backupDir

Donde .ssh / id_rsa es la ruta a su clave privada. Esta es la línea exacta que estoy usando para hacer mis copias de seguridad y siempre funciona bien para mí.

Mis mejores deseos,
Fabián

Halfdan
fuente
0

Como alternativa, en lugar de utilizar el agente ssh, hice que mi script exportara RSYNC_RSH = "ssh -i /home/user/.ssh/id_rsa" unset SSH_AGENT_PID unset SSH_AUTH_SOCK antes de invocar rsync. Al ponerlo en RSYNC_RSH en lugar de usar '-e ...', facilitó el ajuste del archivo de identificación que se usa en función del host.

Espero que esto ayude, B


fuente
No creo que esto funciona si tiene una frase de contraseña en su clave
cmcginty