Як rsync файли між двома пультами?


54

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

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

Які ще обхідні шляхи / команди я можу використати для досягнення подібних результатів?



1
Насправді ви можете rsync між двома віддаленими хостами, використовуючи sshfs на 3-му хості. Просто використовуйте sshfs для встановлення host1 та host2 на хост 3. Потім rsync між 1 та 2.
Вільям Легг

@WilliamLegg недоліком використання sshfsє те, що потім rsyncбачить вихідні та цільові файлові системи як локальні, тому він вимикає його дельта-алгоритм. У цей момент ви майже можете просто використовувати cp -p. Дивіться відповідь, яка пропонує це, та подальші коментарі.
roaima

Відповіді:


50

Як ви виявили, ви не можете використовувати rsync з віддаленим джерелом та віддаленим пунктом призначення. Якщо два сервери не можуть безпосередньо спілкуватися один з одним, можна використовувати ssh для тунелю через локальну машину.

Замість

rsync -vuar host1:/var/www host2:/var/www

ви можете використовувати це

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

Якщо вам цікаво, -Rопція встановлює зворотний канал від порту 50000 на хості1, який відображає (через вашу локальну машину) на порт 22 на хост2. Немає прямого зв’язку від хоста1 до хоста2.


1
Мені подобається рішення @ roaima, але я не міг змусити його працювати для мене через різні причини. Врешті-решт я використовував sshfsлокальні монтажі обох віддалених каталогів, а потім використовувався rsyncчерез два локально встановлені каталоги.
помічник

Можливо побачити приклад, де використовується ключ? Не вдається з'ясувати, як за допомогою -iвказати ключі, необхідні для ssh-команд.
onassar

@onassar додайте -i key...параметр всередині лапок після sshкоманди. Якщо це не допоможе вам, будь ласка, не соромтесь задавати нове запитання, посилаючись на цю відповідь у контексті
roaima

1
зворотне з'єднання не читає ~ / .ssh / config на локальній стороні - потрібно використовувати щось, що можна вирішити, як ніби не було конфігураційного файлу SSH
Florenz Kley

1
"Припустимо, що два сервери не можуть спілкуватися безпосередньо один з одним". Це рішення вирішує проблему між брандмауером або NAT, що запобігає прямому з'єднанню SSH . Однак він не стосується випадку, коли з міркувань безпеки у вихідного користувача (на хості1) немає ключа або облікових даних або недостатнього дозволу на запис у пункті призначення. Для цього дивіться рішення Кевіна Кокса або вдайтеся до непрямого з'єднання за допомогою сценарію або scp -3.
Седрік Лицар

22

Ви не сказали, чому ви не хочете увійти в один хост, а потім скопіювати на інший, тож я поділюсь однією з моїх причин та рішень.

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

ПОПЕРЕДЖЕННЯ: Пересилання SSH дозволяє хосту використовувати ваш ключ SSH протягом часу вашого входу. Хоча вони не можуть скопіювати ваш ключ, вони можуть увійти в нього на інших машинах. Переконайтеся, що ви розумієте ризики та не використовуйте переадресацію агентів для машин, яким ви не довіряєте.

Наступна команда буде використовувати SSH перенаправлення агента , щоб відкрити пряме з'єднання з host1до host2. Це має перевагу в тому, що машина, що виконує команду, не обмежує передачу.

ssh -A host1 rsync -vuar /var/www host2:/var/www

3
+1 для пояснення дійсного випадку використання (коли віддалений користувач у хості1 не має дозволів на сервері призначення); важливий застереження щодо безпеки (використовуйте переадресацію портів, -Dа не -Aдля обходу мережі, а не ключових обмежень); для пояснення переваги; щоб команда була короткою; і це насправді працює. Зауважте, що вам може знадобитися вказати, username@host1чи воно відрізняється від локального імені користувача. Крім того, що rsync виконує перевірку ключів хоста під час підключення до хоста2, тому ключ хоста1 вже повинен бути у ~ / .ssh / known_hosts на хості2, інакше команда не вдасться.
лицар Седрік

Феноменальна відповідь, це допомогло мені організувати деякі речі в TeamCity, що я раніше не міг зробити (нб для інших користувачів TeamCity, ви повинні додати "Конфігурацію функції" під назвою "Агент SSH" до своєї конфігурації збірки перед використанням ssh -A, див. Злиття. jetbrains.com/display/TCD10/SSH+Agent ).
Джон Цвінк

12

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

rsync -vuar host1:/host1/path host2:/host2/path

Але це так (я випустив явну bind_address localhost з -Rпараметра, оскільки це за замовчуванням):

ssh -R 50000:host2:22 host1 'rsync -e "ssh -p 50000" -vuar /host1/path localhost:/host2/path'

Зауважте, що вам доведеться правильно встановити ключі ssh між двома віддаленими хостами, приватним ключем на хості1 та відкритим ключем на хості2.

Щоб налагодити з'єднання, розірвіть це на дві частини та додайте багатослівний статус:

localhost$ ssh -v -R 50000:host2:22 host1

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

host1$ rsync -e "ssh -p 50000" -vuar /host1/path localhost:/host2/path

У моєму прикладі шляхи є джерелом, пунктом призначення. rsyncІніціюється на host1 з мішенню на host2. (Ви могли попросити роз'яснення у коментарі.)
roaima

1
Я б прокоментував, але ви не можете коментувати чужий пост без репутації 50+.
jaybrau

7

Відповідь від переформатування від roaima у синтаксисі сценарію bash (та додавання символів продовження рядка '\' для ясності) Я випадковим чином вибрав порт 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"

1
мені здається, що все, що ви зробили, це замінити його довільні імена хостів змінними?
Джефф Шаллер

3
Так. Для мене це додає ясності, на якій саме машині джерела, яка мішень і куди йдуть вихідні та цільові шляхи. Мені знадобилося деякий час, щоб все це виправити, і це було не очевидно з простих імен хостів-заповнювачів.
Давид I.

Наступного разу будь ласка сміливо покращуючи чужу відповідь безпосередньо, відредагувавши її.
roaima

Ця відповідь була вирішенням для мене, оскільки вона поєднує перенаправлення ssh-агента (-A) з зворотним тунелем (-R).
camelthemammel

3

Ідеальним способом було б запуск rsyncна одному з цих серверів. Але якщо ви не хочете запускати скрипт на віддаленому сервері. Ви можете запустити скрипт у вашій локальній системі, зробити ssh та виконати rsync там.

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

Крім того, як ви, мабуть, знаєте, rysnc здійснює один спосіб синхронізації. Якщо вам потрібна двостороння синхронізація, ви можете переглянути osync ( https://github.com/deajan/osync ). Я використовую його і вважаю, що це корисно.


0

Як додаткова інформація:

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

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

SSHFS забезпечує два шляхи на хості стрибків, а rsync керує синхронізацією файлів, як завжди (лише з тією різницею, що це практично робиться локально).


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

0

Ви можете запустити rsyncd (сервер) на одному з комп'ютерів.

Це такий підхід, який я використовую, оскільки я не хочу використовувати ssh, щоб дозволити 'source' (у формулюванні rsync) отримати доступ до пункту призначення як root без пароля (як це потрібно для тунелювання SSH з rsync в сценарій)

У моєму випадку я просто встановив сервер rsyncd на цільовому комп’ютері з одним користувачем, дозволеним з вихідного ПК та використовував rsync з боку джерела.

Чудово працює.


0

Спробуйте скористатися цим. Це працює для мене.

ssh src_user@src_host 'rsync -av /src/dir/location/ dest_user@dest_host:/dest/dir/loc/'

0

Простий у використанні сценарій

Протягом багатьох років я робив це багато разів з більш-менш тими ж хитрощами, як і в будь-якій іншій відповіді тут. Однак тому, що зрозуміти деталі неправильно і витратити багато часу на роз'яснення проблеми, я придумав сценарій нижче, це дуже просто:

  1. Легко вказувати всі деталі (джерело, призначення, параметри)
  2. Поступово перевіряє кожен крок і дає відгуки, якщо щось піде не так, щоб ви знали, що виправити.
  3. Вирішує випадки, коли ssh -Aне вдається поширити дані автентифікації (не знаю, чому це відбувається іноді, оскільки вирішення було простіше, ніж пошук першопричини)
  4. Нарешті виконує роботу.

Як користуватися сценарієм

  1. Переконайтеся, що ви можете сш на обидва хости з localhost, не вводячи пароль.
  2. Встановіть змінні в перші кілька рядків сценарію
  3. Виконай його.

Як це працює

Як я вже говорив, він використовує ті самі хитрощі, як і в будь-якій іншій відповіді тут:

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

tarчудово, коли у вас є одна (не-додаткова) передача, і ваша передача завершується за один пропуск. З іншого боку, rsyncз ручками переадресації перезапускається та збільшується передача.
roaima

1
Звичайно @roaima - я не вважаю еквівалент смоли. Я залишив цю прохідну довідку на день, коли я буду читати це, щоб вирішити проблему, коли rsync не буде на 100% необхідним.
ndemou

-1

Можна використовувати tarчерез sshдля передачі файлів:

ssh -n user1@host1 'tar jcf - -C /var/www .' | ssh user2@host2 'tar jxvf - -C /var/www'

Змініть jпараметр (for tar) на zдва місця, якщо ви бажаєте gzipзамість цього стиснути архів bzip2. Зазвичай bzip2має більш високу компресію, ніж gzip, але вона повільніше, тому змінюйте її залежно від ваших потреб (див.: Bzip2 vs gzip ).

Пов’язано: Як скопіювати між двома віддаленими хостами за допомогою дьогтю, перекладеного в SSH з віддаленого сервера, коли за брандмауером?


Альтернативно (для забезпечення пропускної здатності через прозорого стиснення) можна використовувати sshfsдля монтажу віддаленої файлової системи як локальну та використовувати rsyncяк зазвичай, наприклад

$ sshfs user1@host1:/var/www /mnt
$ rsync -vuar /mnt user2@host2:/var/www

1
Під час монтажу файлової системи локально не вдається зберегти пропускну здатність між джерелом та локальною машиною. Однак це дозволить зберегти пропускну здатність між локальним та місцевим призначенням (оскільки він не встановлений локально). Використовувати rsync таким чином, має сенс лише якщо ви намагаєтесь зберегти пропускну здатність у пункті призначення.
Кевін Кокс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.