rsync-хак для відмов файлів між двома непоєднаними серверами


8

Ось підключення:

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

Server1 і server2 заборонено спілкуватися безпосередньо з іншими (не запитувати). Однак мій робочий стіл може отримати доступ до обох серверів через ssh.

Мені потрібно скопіювати файли з server1 на server2.

Традиційно я використовую ssh + tar hack як такий:

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

І це чудово працює, але я хотів би зробити його крок далі і примусити rsync працювати між двома серверами VIA на моєму робочому столі.

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

  • Одна команда вкладиша для rsync файлів з Server1 на server2 VIA мого робочого столу
  • всі в одному командному рядку, одне вікно терміналу
  • Я хочу, щоб тунель переходу в порт існував лише протягом життя команди rsync.
  • Я не хочу робити scp, я хочу rsync.

Хтось має хитрість робити це?

EDIT: Ось робоча команда! Відмінна робота для всіх: 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 = немає після прапорців -p або -i.
Amala

Відповіді:


5

Якщо ви раді зберігати копію даних на проміжній машині, тоді ви можете просто написати сценарій, який оновив локальну копію за допомогою сервера1 як посилання, а потім оновив резервну копію на сервері2, використовуючи локальну копію як довідку:

#!/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

Використання простого сценарію означає, що ви хотіли, щоб одна команда виконала все. Звичайно, це може бути безпекою, ні - якщо дані є конфіденційними (ви або інші особи у вашій компанії, можливо, не хочете, щоб копія плавала навколо вашого ноутбука). Якщо сервер1 є локальним для вас, ви можете просто видалити локальну копію згодом (оскільки це буде швидко відновити через локальну локальну мережу наступного разу).

Побудувати тунель, щоб сервери могли ефективніше спілкуватися один з одним безпосередньо, повинно бути можливим так:

  1. На сервері 2 зробіть копію / bin / sh as / usr / local / bin / shforkeepalive. Використовуйте символічне посилання, а не копію, тоді ви цього не робите; не потрібно буде оновлювати його після оновлень безпеки, які патч / бін / ш.
  2. На сервері 2 створіть сценарій, який не робить нічого, крім циклу, який спить протягом декількох секунд, після чого повторюється невелика кількість тексту, і використовуйте для цього тепер "копію" sh:

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

    ( echoнапевно, це не потрібно, оскільки сеанс не буде простоювати досить довго, щоб затримати час, навіть якщо SSHd налаштований ігнорувати збережені пакети від 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 через нього, щоб тримати його відкритим. Trailing & каже bash запустити це у фоновому режимі, щоб наступні рядки могли працювати, не чекаючи, коли він закінчиться
  • Рядок 3: запустіть тунель, який підключиться до тунелю вище, щоб сервер1 міг бачити server2 та запустити rsync, щоб виконати копіювання / оновлення для цієї домовленості
  • Рядок 4: вбити сценарій збереження в живих, коли операція rsync завершиться (і так повернеться другий дзвінок SSH), що буде і першим сеансом ssh.

Це не особливо чисто, але це має працювати. Я не перевіряв вищезазначене, тому вам може знадобитися налаштувати його. Зробити команду rsync однорядковою скриптом на сервері1 може допомогти, зменшивши будь-яку необхідність уникнути символів, таких як 'у виклику команди ssh.

BTW: ви кажете "не запитувати", чому два сервери не можуть бачити один одного безпосередньо, але для цього часто є вагомі причини. Мій домашній сервер і сервер, на якому зберігаються його резервні копії в Інтернеті, не можуть входити один до одного (і мати різні паролі + ключі для всіх користувачів) - це означає, що якщо один з двох зламаний, його не можна використовувати як простий шлях до зламати інше, щоб мої онлайн-резервні копії були безпечнішими (хтось шкідливий, видаляючи мої дані з живих, не може використовувати його здатність оновити резервні копії для видалення зазначених резервних копій, оскільки він не має прямої можливості торкатися головного резервного веб-сайту). Обидва сервери можуть обидва підключитися до проміжного сервера в іншому місці - сервер в реальному часі встановлюється для того, щоб рано вранці проштовхувати його резервні копії (через rsync) на проміжну машину, а сервер резервного копіювання встановлюється (на деякий час пізніше, щоб дозволити завершити крок перший) для підключення і збирати оновлення (знову через rsyc з подальшим кроком зйомки з метою збереження кількох віків резервного копіювання). Ця методика може бути корисною і за ваших обставин, і якщо так, я рекомендував би її як набагато чистіший спосіб робити речі.

Редагувати: Об’єднавши мій хак з Аароном, щоб уникнути всіх маніпуляцій із копіями / bin / sh та окремим сценарієм збереження в режимі "живий" на сервері2, цей сценарій на вашому ноутбуці повинен виконати всю роботу:

#!/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, який передає через інший тунель до localhost сервера2: 22.

Редагування 2: Якщо ви не заперечуєте, щоб сервер1 мав ключ, який дозволяє йому автентифікувати сервер2 безпосередньо (хоча він не може бачити сервер2 без тунелю), ви можете додатково спростити:

#!/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 - це загальнодоступна адреса для сервера2, яка може використовуватися як копія + вставлення однокласника замість сценарію.


Це великий об'єм даних (20 + gb), і я вважаю за краще передавати їх у той чи інший час, а не зберігати локально. Я хочу передавати дані через свій ПК, не зберігаючи нічого. Ви маєте рацію щодо "не запитуйте", це з поважної причини, хоч і піта.
регулятор

Plesae бачить нові зміни в оригінальному запитанні
regulalatre

Я думаю, що моя остання редакція (розміщена за секунди до Вашого коментаря відповідно до часових позначок, тому ми, ймовірно, вводили одночасно), може дати вам шукати один вкладиш.
Девід Спіллетт

ХОРАЙ !!! Це працює! 1. для ключа rsa не можна використовувати тильди, довелося використовувати "/ 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"
регулятор

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

2

Ось кілька методів, які роблять синхронізацію простим однолінійним, але вимагають певної роботи з налаштуванням.

  • Налаштуйте зворотний ssh-тунель з server1 на робочий стіл (вибачте, я не можу сказати вам про .ssh/configзаклик у верхній частині голови). Пов’язати це ланцюжком підключенням від робочого столу до серверу2. Запустіть rsync з сервера1.

  • Встановіть на робочому столі проксі-носок (або http-проксі, який приймає CONNECT). Використовуйте його для встановлення ssh-з'єднання з сервера1 на сервер2. Запустіть rsync з сервера2.

  • Використовуйте унісон замість 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чудовіше, ніж у моїй відповіді метод "зберігайте життя і вбивайте". .
Девід Спіллетт

дивіться правки на оригінальне запитання.
регулятор

Чорт, ти маєш рацію. Не можна вказувати два хости як аргументи на команді ling. ... хммм ..
Аарон Дігулла

Гаразд, я покращив своє рішення. Вам потрібно створити два порти вперед, щоб зробити ssh-сервер server2 видимим на сервері1.
Аарон Дігулла

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