Простий у використанні сценарій
Протягом багатьох років я робив це багато разів з більш-менш тими ж хитрощами, як і в будь-якій іншій відповіді тут. Однак тому, що зрозуміти деталі неправильно і витратити багато часу на роз'яснення проблеми, я придумав сценарій нижче, це дуже просто:
- Легко вказувати всі деталі (джерело, призначення, параметри)
- Поступово перевіряє кожен крок і дає відгуки, якщо щось піде не так, щоб ви знали, що виправити.
- Вирішує випадки, коли
ssh -A
не вдається поширити дані автентифікації (не знаю, чому це відбувається іноді, оскільки вирішення було простіше, ніж пошук першопричини)
- Нарешті виконує роботу.
Як користуватися сценарієм
- Переконайтеся, що ви можете сш на обидва хости з localhost, не вводячи пароль.
- Встановіть змінні в перші кілька рядків сценарію
- Виконай його.
Як це працює
Як я вже говорив, він використовує ті самі хитрощі, як і в будь-якій іншій відповіді тут:
- SSH в
-R
можливість SSH з локального хоста на host1 в той же час при налаштуванні переадресації порту , який потім дозволяє host1 для підключення через локального хоста до host2 ( -R localhost:$FREE_PORT:$TARGET_ADDR_PORT
)
- ssh-
-A
параметр дозволяє легко перевірити автентичність другого ssh-шанелю
Моє це СКЛАДНО! Чи є простіший спосіб?
Під час копіювання всіх або більшість байтів від джерела до місця призначення він FAR простіше у використанні tar
:
ssh $SOURCE_HOST "tar czf - $SOURCE_PATH" \
| ssh $TARGET_HOST "tar xzf - -C $TARGET_PATH/"
Сценарій
#!/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 someuser@1.2.3.4 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"