web-dev-qa-db-fra.com

Comment synchroniser des fichiers entre deux télécommandes?

Je voudrais transférer des fichiers entre deux hôtes distants à l'aide du shell local, mais il semble que rsync ne prend pas en charge la synchronisation si deux télécommandes sont spécifiées comme suit:

$ rsync -vuar Host1:/var/www Host2:/var/www
The source and destination cannot both be remote.

Quelles autres solutions/commandes que je pourrais utiliser pour obtenir des résultats similaires?

60
kenorb

Comme vous l'avez découvert, vous ne pouvez pas utiliser rsync avec une source distante et une destination distante. En supposant que les deux serveurs ne peuvent pas communiquer directement entre eux, il est possible d'utiliser ssh pour tunneler via votre machine locale.

Au lieu de

rsync -vuar Host1:/var/www Host2:/var/www

vous pouvez l'utiliser

ssh -R localhost:50000:Host2:22 Host1 'rsync -e "ssh -p 50000" -vuar /var/www localhost:/var/www'

Au cas où vous vous poseriez la question, le -R L'option configure un canal inverse du port 50000 sur Host1 qui mappe (via votre machine locale) au port 22 sur Host2. Il n'y a pas de connexion directe de Host1 à Host2.

58
roaima

Vous n'avez pas dit pourquoi vous ne vouliez pas vous connecter à un hôte, puis copier sur l'autre, je partagerai donc l'une de mes raisons et solutions.

Je ne pouvais pas me connecter à une machine, puis rsync à l'autre parce qu'aucun des hôtes n'avait de clé SSH qui pouvait se connecter à l'autre. J'ai résolu ce problème en utilisant le transfert d'agent SSH pour permettre au premier hôte d'utiliser ma clé SSH lorsque j'étais connecté.

ATTENTION: Le transfert SSH permet à l'hôte d'utiliser votre clé SSH pendant la durée de votre connexion. Bien qu'ils ne puissent pas copier votre clé, ils peuvent se connecter à d'autres machines avec. Assurez-vous de bien comprendre les risques et n'utilisez pas le transfert d'agent pour les machines auxquelles vous ne faites pas confiance.

La commande suivante utilise le transfert d'agent SSH pour ouvrir une connexion directe à partir de Host1 à Host2. Cela présente l'avantage que la machine exécutant la commande ne gêne pas le transfert.

ssh -A Host1 rsync -vuar /var/www Host2:/var/www
23
Kevin Cox

J'aime la réponse de roaima, mais les chemins sont les mêmes dans les deux exemples, obscurcissant qui est lequel. Nous avons établi que ce qui suit ne fonctionne pas:

rsync -vuar Host1:/Host1/path Host2:/Host2/path

Mais c'est le cas (j'ai omis l'adresse bind_address explicite de localhost dans le -R option puisque c'est la valeur par défaut):

ssh -R 50000:Host2:22 Host1 'rsync -e "ssh -p 50000" -vuar /Host1/path localhost:/Host2/path'

Notez que vous devrez configurer correctement les clés ssh entre les deux hôtes distants, avec la clé privée sur Host1 et la clé publique sur Host2.

Pour déboguer la connexion, divisez-la en deux parties et ajoutez un état détaillé:

localhost$ ssh -v -R 50000:Host2:22 Host1

Si cela fonctionne, vous aurez un Shell sur Host1. Essayez maintenant la commande rsync de Host1. Je recommande de le faire dans une fenêtre différente pour que les informations ssh détaillées ne soient pas mélangées avec les informations d'état rsync:

Host1$ rsync -e "ssh -p 50000" -vuar /Host1/path localhost:/Host2/path
15
jaybrau

Reformatage de la réponse par roaima dans la syntaxe du script bash (et ajout de caractères de continuation de ligne '\' pour plus de clarté) J'ai choisi au hasard le port 22000 ...

SOURCE_USER=user1
SOURCE_Host=hostname1
SOURCE_PATH=path1

TARGET_USER=user2
TARGET_Host=host2
TARGET_PATH=path2

ssh -l $TARGET_USER -A -R localhost:22000:$TARGET_Host:22 \
$SOURCE_USER@$SOURCE_Host "rsync -e 'ssh -p 22000' -vuar $SOURCE_PATH \
$TARGET_USER@localhost:$TARGET_PATH"
8
David I.

L'idéal serait d'exécuter le rsync sur l'un de ces serveurs. Mais si vous ne souhaitez pas exécuter de script sur le serveur distant. Vous pouvez exécuter un script sur votre système local et faire un ssh et y exécuter le rsync.

ssh user@$Host1 <<ENDSSH >> /tmp/rsync.out 2>&1 rsync -vuar /var/www Host2:/var/www ENDSSH

De plus, comme vous le savez peut-être, rysnc effectue une synchronisation unidirectionnelle. Si vous souhaitez une synchronisation bidirectionnelle, vous pouvez consulter osync ( https://github.com/deajan/osync ). Je l'utilise et l'ai trouvé utile.

3
rahul

Vous pouvez exécuter un rsyncd (serveur) sur l'un des ordinateurs.

C'est l'approche que je prends, car je ne veux pas utiliser ssh pour permettre à la 'source' (dans le libellé rsync) d'accéder à la 'destination' en tant que root sans mot de passe (comme cela est nécessaire pour utiliser le tunneling SSH avec rsync dans un script)

Dans mon cas, j'ai simplement configuré un serveur rsyncd sur l'ordinateur de destination avec un seul utilisateur autorisé à partir du PC source et utilisé rsync du côté source.

Fonctionne très bien.

0
RustyCar

n script facile à utiliser

Au fil des ans, j'ai fait cela plusieurs fois avec plus ou moins les mêmes astuces que dans toutes les autres réponses ici. Cependant, parce qu'il est très facile de se tromper en détail et de passer beaucoup de temps à résoudre le problème, j'ai trouvé le script ci-dessous:

  1. Permet de spécifier facilement tous les détails (source, destination, options)
  2. Teste progressivement chaque étape et donne des informations en cas de problème, afin que vous sachiez quoi résoudre.
  3. Fonctionne dans les cas où ssh -A ne parvient pas à propager les données d'authentification (je ne sais pas pourquoi cela se produit parfois car la solution de contournement était plus facile que de trouver la cause première)
  4. Fait enfin le travail.

Comment utiliser le script

  1. Assurez-vous que vous pouvez ssh vers les deux hôtes depuis localhost sans en tapant un mot de passe.
  2. Définissez les variables dans les premières lignes du script
  3. L'exécuter.

Comment ça marche

Comme je l'ai dit, il utilise les mêmes astuces que dans toutes les autres réponses ici:

  • -R option pour ssh de localhost à Host1 tout en configurant une redirection de port qui permet ensuite à Host1 de se connecter via localhost à Host2 (-R localhost:$FREE_PORT:$TARGET_ADDR_PORT)
  • -A option pour permettre une authentification facile du deuxième canal ssh

Mon ceci IS compliqué! Y at-il un moyen plus facile?

Lors de la copie de la totalité ou de la plupart des octets de la source vers la destination, il est LOIN plus facile à utiliser tar:

ssh $SOURCE_Host "tar czf - $SOURCE_PATH" \
    | ssh $TARGET_Host "tar xzf - -C $TARGET_PATH/"

Le script

#!/bin/bash
#-------------------SET EVERYTHING BELOW-------------------
# whatever you type after ssh to connect to SOURCE/TARGE Host 
# (e.g. 1.2.3.4:22, user@Host:22000, ssh_config_alias, etc)
# So if you use "ssh foo" to connect to SOURCE then 
# you must set SOURCE_Host=foo
SOURCE_Host=host1 
TARGET_Host=host2 
# The IP address or hostname and ssh port of TARGET AS SEEN FROM LOCALHOST
# So if ssh -p 5678 [email protected] will connect you to TARGET then
# you must set TARGET_ADDR_PORT=1.2.3.4:5678 and
# you must set TARGET_USER=someuser
TARGET_ADDR_PORT=1.2.3.4:5678
TARGET_USER=someuser

SOURCE_PATH=/mnt/foo  # Path to rsync FROM
TARGET_PATH=/mnt/bar  # Path to rsync TO

RSYNC_OPTS="-av --bwlimit=14M --progress" # rsync options
FREE_PORT=54321 # just a free TCP port on localhost
#---------------------------------------------------------

echo -n "Test: ssh to $TARGET_Host: "
ssh $TARGET_Host echo PASSED| grep PASSED || exit 2

echo -n "Test: ssh to $SOURCE_Host: "
ssh $SOURCE_Host echo PASSED| grep PASSED || exit 3

echo -n "Verifying path in $SOURCE_Host "
ssh $SOURCE_Host stat $SOURCE_PATH | grep "File:" || exit 5

echo -n "Verifying path in $TARGET_Host "
ssh $TARGET_Host stat $TARGET_PATH | grep "File:" || exit 5

echo "configuring ssh from $SOURCE_Host to $TARGET_Host via locahost"
ssh $SOURCE_Host "echo \"Host tmpsshrs; ControlMaster auto; ControlPath /tmp/%u_%r@%h:%p; hostname localhost; port $FREE_PORT; user $TARGET_USER\" | tr ';' '\n'  > /tmp/tmpsshrs"

# The ssh options that will setup the tunnel
TUNNEL="-R localhost:$FREE_PORT:$TARGET_ADDR_PORT"

echo 
echo -n "Test: ssh to $SOURCE_Host then to $TARGET_Host: "
if ! ssh -A $TUNNEL $SOURCE_Host "ssh -A -F /tmp/tmpsshrs tmpsshrs echo PASSED" | grep PASSED ; then
        echo
        echo "Direct authentication failed, will use plan #B:"
        echo "Please open another terminal, execute the following command"
        echo "and leave the session running until rsync finishes"
        echo "(if you're asked for password use the one for $TARGET_USER@$TARGET_Host)"
        echo "   ssh -t -A $TUNNEL $SOURCE_Host ssh -F /tmp/tmpsshrs tmpsshrs"
        read -p "Press [Enter] when done..."
fi

echo "Starting rsync"
ssh -A $TUNNEL $SOURCE_Host "rsync -e 'ssh -F /tmp/tmpsshrs' $RSYNC_OPTS $SOURCE_PATH tmpsshrs:$TARGET_PATH"

echo
echo "Cleaning up"
ssh $SOURCE_Host "rm /tmp/tmpsshrs"
0
ndemou

Essayez d'utiliser ceci. Ça marche pour moi.

ssh src_user@src_Host 'rsync -av /src/dir/location/ dest_user@dest_Host:/dest/dir/loc/'
0
Nikhil Pandey

Juste comme info supplémentaire:

Si vous utilisez un hôte de connexion pour connecter les deux autres machines mais qu'elles ne peuvent pas se joindre directement, vous pouvez utiliser sshfs comme support entre ces deux machines comme ceci (sur l'hôte de connexion):

$ mkdir ~/sourcepath ~/destpath
$ sshfs sourcehost:/target/dir ~/sourcepath
$ sshfs desthost:/target/dir ~/destpath
$ rsync -vua ~/sourcepath ~/desthpath

SSHFS fournit les deux chemins sur l'hôte de saut et rsync gère la synchronisation des fichiers comme toujours (à la différence près que cela se fait pratiquement localement).

0
Roger Lehmann