İki uzaktan kumanda arasında dosyaları nasıl senkronize edebilirim?


54

Yerel kabuk kullanarak iki uzak ana bilgisayar arasında dosya aktarmak istiyorum, ancak iki uzaktan kumanda aşağıdaki gibi belirtilirse rsync eşitlemeyi desteklemiyor gibi görünüyor:

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

Benzer sonuçlar elde etmek için başka hangi geçici çözümleri / komutları kullanabilirim?



1
Aslında, 3. ana bilgisayardaki sshfs'leri kullanarak 2 uzak ana bilgisayar arasında rsync yapabilirsiniz. Sadece host1 ve host2'yi host 3'e monte etmek için sshfs kullanın. Ardından 1 ile 2 arasında rsync yapın.
William Legg

Kullanarak dezavantajı @WilliamLegg sshfso olduğu rsyncyerel olarak kaynak ve hedef dosya sistemleri görür, bu nedenle delta algoritması devre dışı bırakır. Bu noktada neredeyse sadece kullanmak kadar iyi olabilir cp -p. Bkz bu önermektedir cevabını ve daha sonraki yorumlar.
roaima,

Yanıtlar:


50

Keşfettiğiniz gibi, rsync'i uzak bir kaynak ve uzak bir hedef ile kullanamazsınız. İki sunucunun doğrudan birbiriyle konuşamayacağını varsayarsak, yerel makineniz üzerinden tünel açmak için ssh kullanmak mümkündür.

Onun yerine

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

bunu kullanabilirsin

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

Merak ediyorsanız, -Rseçenek ana makinedeki1 50000 numaralı bağlantı noktasından ana makinedeki2 bağlantı noktasını (yerel makineniz üzerinden) ana bilgisayar 22'deki bağlantı noktası 22'ye ayarlar. Host1'den host2'ye doğrudan bir bağlantı yoktur.


1
@ Roaima'nın çözümünü seviyorum, ancak çeşitli nedenlerden dolayı benim için çalışmasını sağlayamadım. Sonunda sshfsher iki uzak dizini yerel olarak bağlardım, sonra rsyncyerel olarak bağlanmış iki dizinin karşısında kullanılır .
aidan

Bir anahtarın kullanıldığı bir örneği görmek mümkün mü? -iSsh komutları için gerekli anahtarları belirlemek için nasıl kullanılacağını bulmakta güçlük çekmek .
onassar

@onassar -i key..., sshkomuttan sonra parametreyi tırnak içine ekleyin . Bu size yardımcı olmuyorsa, lütfen Yeni Bir Soru sormaktan çekinmeyin, bu cevabı bağlam için referansta
bulunun

1
ters bağlantı yerel taraftaki ~ / .ssh / config dosyasını
okumaz

1
'İki sunucunun doğrudan birbirleriyle konuşamayacağını farz etmek'. Bu çözüm, doğrudan SSH bağlantısını engelleyen bir güvenlik duvarı veya NAT sorunu etrafında çalışır . Ancak, güvenlik nedeniyle kaynak kullanıcının (ana bilgisayar1'de) hiçbir anahtar veya kimlik bilgisi veya hedefte yetersiz yazma izni bulunmadığı durumu ele almaz. Bunun için Kevin Cox’un çözümünü görün veya bir komut dosyası kullanarak dolaylı bir bağlantıya başvurun scp -3.
Cedric Knight,

22

Neden bir ana bilgisayara oturum açmak istemediğinizi ve ardından diğerine kopyalamak istemediğinizi söylemediniz, bu yüzden nedenlerimden ve çözümlerden birini paylaşacağım.

Bir makineye giriş yapamadım, sonra diğerine rsync yapamadım çünkü hiçbirinde diğerinde oturum açabilecek bir SSH anahtarı yoktu. Bunu, oturum açarken ilk ana makinenin SSH anahtarımı kullanmasına izin vermek için SSH aracısı yönlendirmesini kullanarak çözdüm.

UYARI: SSH iletme, ev sahibinin SSH anahtarınızı oturum açma süresince kullanmasına izin verir. Anahtarınızı kopyalayamasalar da, onunla diğer makinelere giriş yapabilirler. Riskleri anladığınızdan ve güvenmediğiniz makineler için aracı yönlendirmeyi kullanmadığınızdan emin olun.

Aşağıdaki komuttan doğrudan bağlantı açmak için SSH aracı iletmeyi host1kullanacak host2. Bu, komutu çalıştıran makinenin aktarımı engellememesi avantajına sahiptir.

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

3
Geçerli bir kullanım durumunu açıklamak için +1 (burada ana bilgisayar1'deki uzak kullanıcının hedef sunucuda izni yoktur); önemli güvenlik ihbarı için ( anahtar kısıtlamalardan ziyade ağı dolaşmak -Dyerine bağlantı noktası yönlendirmeyi kullanın -A); avantajı açıklamak için; komutun kısa olması için; ve aslında çalışıyor. username@host1Yerel kullanıcı adından farklı olup olmadığını belirtmeniz gerekebileceğini unutmayın . Ayrıca, rsync, host2'ye bağlanırken host anahtarı doğrulamasını yapar, bu yüzden host1'in anahtarı host2'de ~ / .ssh / known_hosts içinde olmalıdır, aksi halde komut başarısız olur.
Cedric Knight,

Olağanüstü cevap, bu beni hiç (diğer TeamCity kullanıcıları için nb önce yapmak mümkün değildi TeamCity bazı şeyleri düzenlenmesine yardım, sen kullanmadan önce inşa config "SSH ajanı" olarak adlandırılan "İnşa Özelliği" eklemelisiniz ssh -Abkz izdiham. jetbrains.com/display/TCD10/SSH+Agent ).
John Zwinck

12

Roaima'nın cevabını seviyorum, ama hangisinin hangisi olduğu belirsiz, her iki örnekte de yollar aynı. Aşağıdakilerin işe yaramadığını tespit ettik:

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

Ancak bu ( -Rvarsayılan olandan beri , localhost'un açık bind_address seçeneğini bu seçeneğin dışında bıraktım ):

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

İki uzak ana bilgisayar arasında, ana bilgisayar1 üzerindeki özel anahtar ve ana bilgisayar2 üzerindeki genel anahtarla, doğru şekilde ssh anahtarlarının kurulması gerektiğini unutmayın.

Bağlantıda hata ayıklamak için, bunu iki parçaya bölün ve ayrıntılı durum ekleyin:

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

Bu işe yararsa, host1'de bir kabuğunuz olur. Şimdi host1'den rsync komutunu deneyin. Bunu farklı bir pencerede yapmanı öneriyorum, böylece ssh bilgisi ayrıntılı bilgisi rsync durum bilgisi ile karışmaz:

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

Benim örneğimde yollar kaynak, hedef. Bu rsync, host1'de host2'de hedefle başlatılır. (Bir yorumda açıklama talebinde bulunabilirdin.)
roaima

1
Ben yorum yapardım, fakat 50'den fazla itibar almadan başka birinin gönderisine yorum yapamazsınız .
jaybrau,

7

Roaima tarafından bash betiği sözdiziminde cevabı yeniden biçimlendirme (ve netlik için satır devam karakterleri '\' ekleyerek) Rastgele 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
Bana öyle geliyor ki, keyfi ana bilgisayar adlarını değişkenlerle değiştirmek mi?
Jeff Schaller

3
Evet yaptım. Kaynak makinenin hangisi, hedef hangisi ve kaynak ve hedef yollarının nereye gittiğine netlik katıyor. Tüm bunları çözmek biraz zaman aldı ve basit yer tutucu ana bilgisayar adlarından belli değildi.
David I.

Bir dahaki sefere lütfen başkasının cevabını doğrudan düzenleyerek geliştirmek için çekinmeyin.
roaima

Bu cevap benim için çözüm oldu çünkü ssh-agent yönlendirme (-A) 'ı ters tünelle (-R) birleştirdi.
camelthemammel

3

İdeal yol rsyncbu sunuculardan birini çalıştırmak olacaktır . Ancak uzak sunucuda bir komut dosyası çalıştırmak istemiyorsanız. Yerel sisteminizde bir komut dosyası çalıştırabilir ve bir ssh yapabilir ve orada rsync komutunu çalıştırabilirsiniz.

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

Ayrıca, bildiğiniz gibi rysnc tek yönlü bir senkronizasyon yapar. İki yönlü senkronizasyon yapmak istiyorsanız, osync'e bakabilirsiniz ( https://github.com/deajan/osync ). Kullanıyorum ve yararlı buldum.


0

Sadece ek bilgi olarak:

Diğer iki makineyi bağlamak için bir atlama sunucusu kullanıyorsanız ancak birbirlerine doğrudan erişemiyorlarsa, bu gibi iki makine arasında sshfs kullanabilirsiniz (atlama sunucusunda):

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

SSHFS, atlama sunucusundaki iki yolu sağlar ve rsync, dosyaların her zamanki gibi eşitlenmesini yönetir (hemen hemen yerel olarak yapıldığı fark ile).


1
Performansın korkunç olacağını unutmayın. Bunun sebebi değişiklikleri algılamak için, rsync dosyayı kaynak sunucudan okuyacak ve her şeyi ağ üzerinden aktaracaktır. Doğrudan transfer yapamıyorsanız, rsync kullanıyorsanız bunu yemek zorunda kalacaksınız. Ayrıca hedefi takmayın, gereksizdir ve rsync'in bazı varsayılanları değiştirmesine neden olur çünkü yerel bir diskle konuştuğunu düşünüyor.
Kevin Cox,

0

Bilgisayarlardan birinde bir rsyncd (server) çalıştırabilirsiniz.

Bu benim yaklaşımım, çünkü 'kaynak' (rsync ifadelerinde) 'hedef' e şifre olmadan root olarak 'hedef' e erişim sağlamak istemem çünkü ss kullanmak istemiyorum. Bir komut dosyası)

Benim durumumda, sadece hedef bilgisayardaki kaynak bilgisayardan izin verilen tek bir kullanıcı ile bir rsyncd sunucusu kurdum ve kaynak tarafından rsync kullandım.

Harika çalışıyor.


0

Bunu kullanmayı dene. Benim için çalışıyor.

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

0

Komut dosyası kullanmak kolay

Yıllar boyunca, buradaki diğer cevapların çoğunda aynı hilelerle aynı şeyi yaptım. Bununla birlikte, bazı ayrıntıları yanlış anlamak ve çok zaman harcamak, çünkü aşağıdaki betiği bularak bu sorunu çözmek için çok kolay:

  1. Tüm detayları belirtmeyi kolaylaştırır (kaynak, hedef, seçenekler)
  2. Her bir adımı aşamalı olarak test eder ve bir şeyler ters gittiğinde geri bildirim verir, böylece ne düzelteceğinizi bilirsiniz.
  3. ssh -AKimlik doğrulama verilerini yaymadığı durumlarda çalışır (geçici çözümün kök nedenini bulmaktan daha kolay olduğu için bunun neden olduğunu bilmiyoruz)
  4. Sonunda iş yapıyor.

Komut dosyası nasıl kullanılır?

  1. Eğer localhost'tan hem ana bilgisayarlara ssh emin olun olmadan bir şifre yazarak.
  2. Değişkenleri betiğin ilk birkaç satırına ayarlayın
  3. Onu çalıştır.

Nasıl çalışır

Dediğim gibi, buradaki diğer cevaplarda olduğu gibi aynı püf noktaları kullanıyor:

  • ssh'nin -Rsonra aynı anda host1 anabilgisayar2'nin için localhost üzerinden bağlanmak sağlayan bir port yönlendirmesi kurulurken seçeneği (localhost dan anabilgisayar1 için ssha -R localhost:$FREE_PORT:$TARGET_ADDR_PORT)
  • ssh'in -Aikinci ssh kanalının kolayca doğrulanmasına izin verme seçeneği

Bu benim karışık. Daha kolay bir yolu var mı?

Tüm ya da çoğu baytı kaynaktan hedefe kopyalarken FAR'ın kullanımı daha kolaydır tar:

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

Senaryo

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

tartek (artımlı olmayan) bir aktarımınız olduğunda ve aktarımınız tek bir geçişte tamamlandığında harikadır . Öte yandan, rsyncyönlendirme tutamaçları ile yeniden başlar ve artan transferler.
roaima

1
Elbette @roaima - Katran eşdeğeri olarak düşünmüyorum. Bu geçici referansı, rsync'in% 100 gerekli olmayacağı bir sorunu çözmek için okuyacağım gün için bıraktım.
ndemou

-1

Dosyaları aktarmak için taryoluyla kullanmak mümkündür ssh:

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

Arşivi yerine sıkıştırmak istiyorsanız, j(for tar) parametresini ziki yerde değiştirin . Genellikle daha yüksek sıkıştırmaya sahiptir , ancak yavaştır, bu nedenle ihtiyaçlarınıza bağlı olarak değiştirin (bkz: bzip2 vs gzip ).gzipbzip2bzip2gzip

İlgili: Güvenlik duvarı arkasındayken uzak sunucudan SSH'ye katranlı boru kullanarak iki uzak ana bilgisayar arasında nasıl kopyalanır?


Alternatif olarak (şeffaflığı nedeniyle bant genişliğini korumak için) sshfs, uzak dosya sistemini yerel olarak monte etmek ve rsyncher zamanki gibi kullanmak mümkündür ;

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

1
Dosya sisteminin yerel olarak monte edilmesi, kaynak ile yerel makine arasındaki bant genişliğinden tasarruf etmeyecektir. O edecek (yerel olarak bağlı değil gibi) ancak yerel ve hedef arasındaki bant genişliği kaydedin. Rsync'i bu şekilde kullanmak, yalnızca hedefte bant genişliğini kaydetmeye çalışıyorsanız anlamlıdır.
Kevin Cox
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.