взломать rsync для пересылки файлов между двумя неподключенными серверами


8

Вот связь:

[Server1] <---> [my desktop] <---> [Server2]

Сервер1 и сервер2 не могут напрямую общаться друг с другом (не спрашивайте). Мой рабочий стол, однако, может получить доступ к обоим серверам через SSH.

Мне нужно скопировать файлы с сервера1 на сервер2.

Традиционно я использую ssh + tar, как таковой:

ssh -q root@Server1 'tar -vzc /path/to/files ' | ssh -q root@Server2 'tar -vzx -C /'

И это прекрасно работает, но я хотел бы сделать еще один шаг и заставить rsync работать между двумя серверами VIA на моем рабочем столе.

Теперь я знаю, что могу запустить туннель пересылки портов ssh в одном терминале и затем выполнить rsync через этот туннель в другом окне, но я не хочу возиться со вторым терминалом или создавать и разбивать отдельный туннель переадресации портов. что я хочу это:

  • Одна команда liner для rsync файлов с сервера 1 на сервер 2 через мой рабочий стол
  • все в ОДНОЙ командной строке, одно окно терминала
  • Я хочу, чтобы туннель переадресации портов существовал только в течение жизни команды rsync.
  • Я не хочу scp, я хочу rsync.

У кого-нибудь есть хитрость для этого?

РЕДАКТИРОВАТЬ: Вот рабочая команда! Отличная работа для всех: 1. Для пути ключа rsa, не могу использовать tildae, пришлось использовать "/ root /". 2. Вот последняя командная строка:

ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"

Бум идет динамитом.


Это действительно отлично. Единственное, что нужно изменить, это отключить проверку ключа хоста. У вас есть ключ SSH для аутентификации TTYless, но поскольку серверы никогда не общались друг с другом, они не могут проверить ключи хоста. Поэтому лучше отключить его: -o StrictHostKeyChecking = no после флагов -p или -i.
Амала

Ответы:


5

Если вы счастливы сохранить копию данных на промежуточном компьютере, вы можете просто написать сценарий, который обновил локальную копию, используя server1 в качестве ссылки, а затем обновил резервную копию на server2, используя локальную копию в качестве ссылки:

#!/bin/sh
rsync user@server1:/path/to/stuff /path/to/loca/copy -a --delete --compress
rsync /path/to/loca/copy user@server2:/path/to/where/stuff/should/go -a --delete --compress

Использование простого сценария означает, что вам нужна единственная команда, чтобы сделать все. Конечно, это может быть защита «нет-нет», если данные конфиденциальны (вы или другие сотрудники вашей компании, возможно, не захотите, чтобы копия находилась на вашем ноутбуке). Если server1 является локальным для вас, вы можете просто удалить локальную копию впоследствии (так как в следующий раз будет легко восстановить по локальной сети).

Построение туннеля, чтобы серверы могли более эффективно общаться друг с другом, должно быть возможно следующим образом:

  1. На сервере 2 сделайте копию / bin / sh как / usr / local / bin / shforkeepalive. Используйте символическую ссылку, а не копию, тогда вам не нужно обновлять ее после обновлений безопасности, исправляющих / bin / sh.
  2. На сервере 2 создайте сценарий, который выполняет только цикл ожидания в течение нескольких секунд, а затем выводит небольшое количество текста, и использует для этого теперь «копию» sh:

    #!/usr/local/bin/shforkeepalive
    while [ "1" != "0" ]; do
            echo Beep!
            sleep 5
    done
    

    ( echoвероятно, в этом нет необходимости, так как сеанс не будет простаивать достаточно долго для тайм-аута, даже если SSHd настроен на игнорирование пакетов keep-alive от клиента ssh)

  3. Теперь вы можете написать скрипт на своем ноутбуке, который запускает обратный туннель в фоновом режиме, говорит server1 использовать rsync для выполнения операции копирования, а затем убивает обратный туннель, убивая зацикленный скрипт (который закроет сеанс SSH):

    #!/bin/sh
    ssh user@server2 -L2222:127.0.0.1:22 /usr/local/bin/keepalivesctipt &
    ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'
    ssh user@server2 killall shforkeepalive
    

Как это работает:

  • Строка 1: стандартная команда «использовать для интерпретации этого сценария»
  • Строка 2: запустить соединение SSH с обратным туннелем и запустить через него скрипт keepalive, чтобы он оставался открытым. Трейлинг & указывает bash запустить его в фоновом режиме, чтобы следующие строки могли выполняться, не дожидаясь его завершения
  • Строка 3: запустите туннель, который подключится к туннелю выше, чтобы server1 мог видеть server2, и запустите rsync, чтобы выполнить копирование / обновление по этой схеме
  • Строка 4: уничтожить скрипт keep-alive после завершения операции rsync (и, таким образом, возвращается второй вызов SSH), что и первый сеанс ssh.

Это не кажется особенно чистым, но это должно работать. Я не проверял вышеизложенное, поэтому вам может понадобиться настроить его. Создание команды rsync в виде однострочного сценария на сервере server1 может помочь, уменьшив необходимость в экранировании символов, таких как 'в вызывающей команде ssh.

Кстати: вы говорите «не спрашивайте», почему два сервера не могут видеть друг друга напрямую, но для этого часто есть веская причина. Мой домашний сервер и сервер, на котором хранятся его онлайн-резервные копии, не могут войти друг в друга (и имеют разные пароли + ключи для всех пользователей) - это означает, что если один из двух файлов взломан, он не может быть использован как простой путь к взломайте другой, чтобы мои резервные копии в Интернете были безопаснее (кто-то, кто удаляет мои данные из живого хранилища, не может использовать его для обновления резервных копий, чтобы удалить указанные резервные копии, поскольку у него нет прямой возможности доступа к основному сайту резервного копирования). Оба сервера могут подключаться к промежуточному серверу где-либо еще - живой сервер настроен на передачу своих резервных копий (через rsync) на промежуточный компьютер рано утром, а резервный сервер настроен (через некоторое время, чтобы завершить первый шаг) для подключения и собирать обновления (снова через rsyc с последующим шагом моментального снимка для сохранения нескольких возрастов резервного копирования). Эта техника может быть полезна и в ваших обстоятельствах, и если это так, я бы порекомендовал ее как более чистый способ ведения дел.

Редактировать: Объединяя мой взлом с Аароном, чтобы избежать всего этого с копиями / bin / sh и отдельным скриптом keep-alive на server2, этот скрипт на вашем ноутбуке должен делать всю работу:

#!/bin/sh
ssh user@server2 -L2222:127.0.0.1:22 sleep 60 &
pid=$!
trap "kill $pid" EXIT 
ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

Как и в предыдущем примере, rsync подключается к localhost: 2222, который переходит вниз по туннелю к localhost вашего ноутбука: 2222, который пересылает через другой туннель к local2 сервера server2: 22.

Редактировать 2: Если вы не возражаете против наличия у server1 ключа, который позволяет ему проходить аутентификацию на сервере server2 напрямую (даже если он не видит server2 без туннеля), вы можете еще больше упростить:

#!/bin/sh
ssh user@server1 -R2222:123.123.123:22 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

где 123.123.123.123 - это общедоступный адрес для server2, который можно использовать как однострочную копию + вставку вместо сценария.


Это большой объем данных (20+ ГБ), и я предпочитаю передавать и выводить их одновременно, а не хранить локально. Я хочу передавать данные через мой компьютер без каких-либо сохранений. Вы правы насчет "не спрашивай", это по уважительной причине, хотя и лаваш.
Regulatre

Plesae видит новые правки по первоначальному вопросу
regulatre

Я думаю, что мое последнее редактирование (опубликованное за секунды до вашего комментария в соответствии с временными метками, поэтому мы, вероятно, печатали одновременно), может дать вам одну строку, которую вы ищете.
Дэвид Спиллетт

УРА!!! Оно работает! 1. для ключа rsa, не могу использовать tildae, пришлось использовать "/ root /". 2. вот последняя ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"
командная строка

Привет @ Дэвид, спасибо за этот замечательный хак. Однако, чтобы заставить его работать, мне нужен ключ сервера 2 на сервере 1, использующий оба решения (в первом и втором редактировании). Я думаю, что это нормально (переадресация портов или нет, server1 все еще пытается аутентифицироваться на server2), но вы пишете If you don't mind server1 having a key .... Можете ли вы сказать мне, действительно ли возможно избежать наличия ключа server2 на server1, пожалуйста?
ssssteffff

2

Вот несколько методов, которые делают синхронизацию простой однострочной, но требуют некоторых настроек.

  • Установите обратный ssh-туннель от server1 к вашему рабочему столу (извините, я не могу сказать вам .ssh/configзаклинание на макушке). Цепь это с подключением с вашего рабочего стола на сервер2. Запустите rsync с сервера1.

  • Установите прокси socks (или http прокси, который принимает CONNECT) на вашем рабочем столе. Используйте его, чтобы установить ssh-соединение с server1 на server2. Запустите rsync с сервера2.

  • Используйте unison вместо rsync. Но рабочий процесс отличается.

  • Смонтируйте каталоги с одного или обоих серверов на рабочем столе, используя sshfs .


1

Почему одна строка? Используйте небольшой сценарий оболочки:

#!/bin/bash
# Run me on server1

# Create the port forward server1 -> desktop -> server2 (i.e.
# the first forward creates a second tunnel running on the desktop)
ssh -L/-R ... desktop "ssh -L/-R ... server2 sleep 1h" &    
pid=$!

# Kill port forward process on exit and any error
trap "kill $pid" EXIT 

rsync -e ssh /path/to/files/ root@localhost:/path/to/files/on/server2

IIRC, вы можете установить время сна ниже; первый sshне прекратится, пока кто-то использует канал.


Я почти уверен, что rsync не может работать между двумя удаленными серверами по SSH таким образом (только локальный -> удаленный или удаленный -> локальный) - хотя вы используете sleepи trapлучше, чем метод «поддержите и убейте» в моем ответе ,
Дэвид Спиллетт

пожалуйста, смотрите изменения в оригинальном вопросе.
Regulatre

Блин, ты прав. Не разрешается указывать два хоста в качестве аргументов в командной строке. ... хммм ..
Аарон Дигулла

Хорошо, я улучшил свое решение. Вам нужно создать два порта переадресации, чтобы сделать службу ssh server2 видимой на server1.
Аарон Дигулла

Добавьте пару ";" превратить его в однострочник. Идея легче понять с помощью сценария.
Аарон Дигулла
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.