Skip to main content
added 23 characters in body
Source Link
ndemou
  • 3k
  • 2
  • 24
  • 27
  1. Makes it easy to specify all the details easily (source, destination, options)
  2. Incrementally tests every single step and gives feedback if anything goes wrong, so that you know what to fix.
  3. Works around cases where ssh -A fails to propagate authentication data (don't know why this happens sometimes since the workaround was easier than finding the root cause)
  4. Finally does the job.
  1. Makes it easy to specify all the details easily (source, destination, options)
  2. Incrementally tests every single step and gives feedback if anything goes wrong
  3. Works around cases where ssh -A fails to propagate authentication data (don't know why this happens sometimes since the workaround was easier than finding the root cause)
  4. Finally does the job.
  1. Makes it easy to specify all the details (source, destination, options)
  2. Incrementally tests every single step and gives feedback if anything goes wrong, so that you know what to fix.
  3. Works around cases where ssh -A fails to propagate authentication data (don't know why this happens sometimes since the workaround was easier than finding the root cause)
  4. Finally does the job.
Source Link
ndemou
  • 3k
  • 2
  • 24
  • 27

An easy to use script

Over the years I've done this many times with more or less the same tricks as in every other answer here. However because it's very easy to get some detail wrong and spend a lot of time figuring out the issue I've come up with the script below that:

  1. Makes it easy to specify all the details easily (source, destination, options)
  2. Incrementally tests every single step and gives feedback if anything goes wrong
  3. Works around cases where ssh -A fails to propagate authentication data (don't know why this happens sometimes since the workaround was easier than finding the root cause)
  4. Finally does the job.

How to use the script

  1. Make sure you can ssh to both hosts from localhost without typing a password.
  2. Set the variables in the first few lines of the script
  3. Execute it.

How it works

As I said it uses the same tricks as in every other answer here:

  • ssh's -R option to ssh from localhost to host1 while at the same time setting up a port forwarding that then allows host1 to connect via localhost to host2 (-R localhost:$FREE_PORT:$TARGET_ADDR_PORT)
  • ssh's -A option to allow easy authenticaion of the second ssh chanel

My this IS complicated! Is there any easier way?

When copying all or most bytes from source to destination it's FAR easier to use tar:

ssh $SOURCE_HOST "tar czf - $SOURCE_PATH" \ | ssh $TARGET_HOST "tar xzf - -C $TARGET_PATH/" 

The 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"