Làm cách nào để rsync tập tin giữa hai điều khiển từ xa?


54

Tôi muốn chuyển các tệp giữa hai máy chủ từ xa bằng cách sử dụng shell cục bộ, nhưng có vẻ như rsync không hỗ trợ đồng bộ hóa nếu hai điều khiển từ xa được chỉ định như sau:

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

Những cách giải quyết / lệnh khác tôi có thể sử dụng để đạt được kết quả tương tự?



1
Trên thực tế, bạn có thể rsync giữa 2 máy chủ từ xa bằng cách tận dụng sshfs trên máy chủ thứ 3. Chỉ cần sử dụng sshfs để gắn kết host1 và host2 trên máy chủ 3. Sau đó, rsync giữa 1 và 2.
William Legg

@WilliamLegg nhược điểm khi sử dụng sshfslà sau đó rsyncthấy các hệ thống tệp nguồn và đích đều là cục bộ, do đó, nó vô hiệu hóa thuật toán delta của nó. Tại thời điểm đó, bạn gần như có thể sử dụng cp -p. Xem câu trả lời đề xuất này và ý kiến ​​tiếp theo của nó.
roaima

Câu trả lời:


50

Như bạn đã phát hiện ra, bạn không thể sử dụng rsync với nguồn từ xa và đích từ xa. Giả sử hai máy chủ không thể nói chuyện trực tiếp với nhau, có thể sử dụng ssh để tạo đường hầm qua máy cục bộ của bạn.

Thay vì

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

bạn có thể sử dụng cái này

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

Trong trường hợp bạn đang tự hỏi, -Rtùy chọn sẽ thiết lập kênh đảo ngược từ cổng 50000 trên host1 để ánh xạ (thông qua máy cục bộ của bạn) sang cổng 22 trên host2. Không có kết nối trực tiếp từ host1 đến host2.


1
Tôi thích giải pháp của @ roaima, nhưng tôi không thể làm cho nó hoạt động được vì nhiều lý do. Cuối cùng, tôi đã sử dụng sshfsđể gắn kết cả hai thư mục từ xa cục bộ, sau đó được sử dụng rsynctrên hai thư mục được gắn cục bộ.
Aidan

Có thể xem một ví dụ trong đó một khóa được sử dụng? Gặp khó khăn khi tìm ra cách sử dụng -iđể chỉ định các khóa cần thiết cho các lệnh ssh.
onassar

@onassar thêm -i key...tham số bên trong dấu ngoặc kép sau sshlệnh. Nếu điều đó không giúp ích gì cho bạn, vui lòng đặt câu hỏi mới, tham khảo câu trả lời này cho ngữ cảnh
roaima

1
kết nối ngược không đọc ~ / .ssh / config ở phía cục bộ - cần sử dụng một cái gì đó có thể được giải quyết như thể không có tệp cấu hình SSH
Florenz Kley

1
'Giả sử hai máy chủ không thể nói chuyện trực tiếp với nhau'. Giải pháp này hoạt động xung quanh vấn đề tường lửa hoặc NAT ngăn kết nối SSH trực tiếp . Tuy nhiên, nó không giải quyết trường hợp vì lý do bảo mật, người dùng nguồn (trên host1) không có khóa hoặc thông tin xác thực hoặc không đủ quyền ghi vào đích. Để biết điều đó, hãy xem giải pháp của Kevin Cox hoặc sử dụng kết nối gián tiếp bằng cách sử dụng tập lệnh hoặc scp -3.
Hiệp sĩ Cedric

22

Bạn đã không nói lý do tại sao bạn không muốn đăng nhập vào một máy chủ và sau đó sao chép sang máy chủ khác để tôi sẽ chia sẻ một trong những lý do và giải pháp của tôi.

Tôi không thể đăng nhập vào một máy sau đó rsync sang máy khác vì không máy chủ nào có khóa SSH có thể đăng nhập vào máy khác. Tôi đã giải quyết vấn đề này bằng cách sử dụng chuyển tiếp tác nhân SSH để cho phép máy chủ đầu tiên sử dụng khóa SSH của tôi trong khi tôi đăng nhập.

CẢNH BÁO: Chuyển tiếp SSH cho phép máy chủ sử dụng khóa SSH của bạn trong suốt thời gian đăng nhập. Trong khi họ không thể sao chép khóa của bạn, họ có thể đăng nhập vào các máy khác bằng nó. Hãy chắc chắn rằng bạn hiểu các rủi ro và không sử dụng chuyển tiếp đại lý cho các máy bạn không tin tưởng.

Lệnh sau sẽ sử dụng chuyển tiếp tác nhân SSH để mở kết nối trực tiếp từ host1đến host2. Điều này có lợi thế là máy chạy lệnh không bị nghẽn cổ chai khi chuyển.

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

3
+1 để giải thích trường hợp sử dụng hợp lệ (trong đó người dùng từ xa trên host1 không có quyền trên máy chủ đích); cho cảnh báo bảo mật quan trọng (sử dụng chuyển tiếp cổng -Dthay vì -Ađi xung quanh mạng thay vì các hạn chế chính); để giải thích lợi thế; cho lệnh ngắn; và nó thực sự hoạt động. Lưu ý rằng bạn có thể cần chỉ định username@host1nếu nó khác với tên người dùng cục bộ. Ngoài ra, rsync thực hiện xác minh khóa máy chủ khi kết nối với host2, vì vậy khóa của host1 phải có trong ~ / .ssh / unknown_hosts trên host2 nếu không lệnh sẽ bị lỗi.
Hiệp sĩ Cedric

Câu trả lời tuyệt vời, điều này đã giúp tôi sắp xếp một số thứ trong TeamCity mà trước đây tôi không thể làm được (nb đối với những người dùng TeamCity khác, bạn phải thêm "Tính năng xây dựng" được gọi là "Tác nhân SSH" vào cấu hình bản dựng của bạn trước khi sử dụng ssh -A, xem hợp lưu. jetbrains.com/display/TCD10/SSH+Agent ).
John Zwinck

12

Tôi thích câu trả lời của roaima, nhưng các đường dẫn đều giống nhau trong cả hai ví dụ, che khuất cái nào. Chúng tôi đã thiết lập rằng những điều sau đây không hoạt động:

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

Nhưng điều này không xảy ra (tôi đã bỏ qua bind_address rõ ràng của localhost khỏi -Rtùy chọn vì đó là mặc định):

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

Lưu ý rằng bạn sẽ phải có các khóa ssh được thiết lập chính xác giữa hai máy chủ từ xa, với khóa riêng trên host1 và khóa chung trên host2.

Để gỡ lỗi kết nối, chia phần này thành hai phần và thêm trạng thái dài dòng:

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

Nếu điều này hoạt động, bạn sẽ có một vỏ trên host1. Bây giờ hãy thử lệnh rsync từ host1. Tôi khuyên bạn nên thực hiện việc này trong một cửa sổ khác để thông tin ssh dài không bị trộn lẫn với thông tin trạng thái rsync:

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

Trong ví dụ của tôi các đường dẫn là nguồn, đích. Việc rsyncnày được bắt đầu trên host1 với mục tiêu trên host2. (Bạn có thể đã yêu cầu làm rõ trong một bình luận.)
roaima

1
Tôi đã có thể nhận xét, nhưng bạn không thể nhận xét về bài đăng của người khác mà không có danh tiếng trên 50.
jaybrau

7

Định dạng lại câu trả lời bằng roaima theo cú pháp bash script (và thêm các ký tự tiếp tục dòng '\' cho rõ ràng) Tôi chọn ngẫu nhiên cổng 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
Dường như với tôi rằng tất cả những gì bạn đã làm là thay thế tên máy chủ tùy ý của mình bằng các biến?
Jeff Schaller

3
Vâng, tôi đã làm. Nó cho tôi biết rõ hơn về máy nào là máy nguồn, mục tiêu và đường dẫn nguồn và đích đi đâu. Tôi đã mất một lúc để xử lý tất cả những điều đó và không rõ ràng từ tên máy chủ giữ chỗ đơn giản.
David I.

Lần tới xin vui lòng cải thiện câu trả lời của người khác trực tiếp bằng cách chỉnh sửa nó.
roaima

Câu trả lời này là giải pháp cho tôi vì nó kết hợp chuyển tiếp ssh-agent (-A) với đường hầm ngược (-R).
camelthemammel

3

Cách lý tưởng sẽ là chạy rsynctrên một trong những máy chủ đó. Nhưng nếu bạn không muốn chạy một tập lệnh trên máy chủ từ xa. Bạn có thể chạy một tập lệnh trên hệ thống cục bộ của mình và thực hiện một ssh và thực thi rsync ở đó.

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

Ngoài ra, như bạn có thể biết rysnc thực hiện đồng bộ hóa một chiều. Nếu bạn muốn đồng bộ hóa hai chiều, bạn có thể xem osync ( https://github.com/deajan/osync ). Tôi sử dụng nó và thấy nó hữu ích.


0

Cũng như một thông tin bổ sung:

Nếu bạn sử dụng máy chủ nhảy để kết nối hai máy kia nhưng chúng không thể tiếp cận trực tiếp với nhau, bạn có thể sử dụng sshfs làm phương tiện giữa hai máy này như vậy (trên máy chủ nhảy):

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

SSHFS cung cấp hai đường dẫn trên máy chủ nhảy và rsync quản lý việc đồng bộ hóa các tệp như mọi khi (chỉ với sự khác biệt mà hầu như được thực hiện cục bộ).


1
Lưu ý rằng hiệu suất sẽ là khủng khiếp. Điều này là do để phát hiện các thay đổi, rsync sẽ đọc tệp từ máy chủ nguồn, chuyển toàn bộ nội dung qua mạng. Điều đó được nói rằng nếu bạn không thể thực hiện chuyển khoản trực tiếp, bạn sẽ phải ăn món này nếu bạn đang sử dụng rsync. Ngoài ra, không gắn kết đích, điều đó là không cần thiết và sẽ khiến rsync thay đổi một số giá trị mặc định vì cho rằng nó đang nói chuyện với một đĩa cục bộ.
Kevin Cox

0

Bạn có thể chạy rsyncd (máy chủ) trên một trong các máy tính.

Đây là cách tiếp cận tôi đang thực hiện, vì tôi không muốn sử dụng ssh để cho phép 'nguồn' (theo từ ngữ rsync) truy cập vào 'đích' mà không cần mật khẩu (như được yêu cầu sử dụng SSH đường hầm với rsync trong một kịch bản)

Trong trường hợp của tôi, tôi chỉ cần thiết lập một máy chủ rsyncd trên máy tính đích với một người dùng được phép từ máy tính nguồn và sử dụng rsync từ phía nguồn.

Công trình tuyệt vời.


0

Hãy thử sử dụng cái này. Nó làm việc cho tôi.

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

0

Một kịch bản dễ sử dụng

Trong những năm qua, tôi đã thực hiện điều này nhiều lần với ít nhiều thủ thuật giống như mọi câu trả lời khác ở đây. Tuy nhiên vì rất dễ để có một số chi tiết sai và dành nhiều thời gian để tìm ra vấn đề tôi đã đưa ra với kịch bản dưới đây:

  1. Giúp dễ dàng chỉ định tất cả các chi tiết (nguồn, đích, tùy chọn)
  2. Kiểm tra tăng dần từng bước một và đưa ra phản hồi nếu có sự cố xảy ra, để bạn biết phải sửa gì.
  3. Hoạt động xung quanh các trường hợp ssh -Akhông truyền bá dữ liệu xác thực (đôi khi không biết tại sao điều này xảy ra vì cách giải quyết dễ hơn tìm ra nguyên nhân gốc)
  4. Cuối cùng cũng làm được việc.

Cách sử dụng tập lệnh

  1. Hãy chắc chắn rằng bạn có thể ssh đến cả hai máy chủ từ localhost mà không cần nhập mật khẩu.
  2. Đặt các biến trong một vài dòng đầu tiên của tập lệnh
  3. Thực hiện nó.

Làm thế nào nó hoạt động

Như tôi đã nói, nó sử dụng các thủ thuật giống như trong mọi câu trả lời khác ở đây:

  • -RTùy chọn của ssh để ssh từ localhost sang host1 đồng thời thiết lập chuyển tiếp cổng sau đó cho phép host1 kết nối qua localhost với host2 ( -R localhost:$FREE_PORT:$TARGET_ADDR_PORT)
  • -Atùy chọn của ssh để cho phép xác thực dễ dàng của ssh chanel thứ hai

Cái này của tôi thật phức tạp! Có cách nào dễ dàng hơn không?

Khi sao chép tất cả hoặc hầu hết các byte từ nguồn đến đích, FAR dễ sử dụng hơn tar:

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

Kịch bản

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

tarthật tuyệt vời khi bạn có một lần chuyển (không tăng) chuyển của bạn hoàn thành trong một lần duy nhất. Mặt khác, rsyncvới tay cầm chuyển tiếp khởi động lại và chuyển tiền gia tăng.
roaima

1
Tất nhiên @roaima - Tôi không xem xét tương đương tar. Tôi đã để lại tài liệu tham khảo vượt qua này vào ngày mà tôi sẽ đọc nó để giải quyết vấn đề trong đó rsync sẽ không cần thiết 100%.
ndemou

-1

Có thể sử dụng tarthông qua sshđể chuyển các tập tin:

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

Thay đổi jtham số (cho tar) thành zhai nơi nếu bạn muốn nén tệp lưu trữ gzip, thay vì bzip2. Thường bzip2có độ nén cao hơn gzip, nhưng chậm hơn, vì vậy hãy thay đổi tùy theo nhu cầu của bạn (xem: bzip2 so với gzip ).

Liên quan: Làm thế nào để sao chép giữa hai máy chủ từ xa bằng tar được chuyển sang SSH từ máy chủ từ xa khi ở phía sau tường lửa?


Ngoài ra (để bảo vệ băng thông, do nén trong suốt), có thể sử dụng sshfsđể gắn hệ thống tệp từ xa làm cục bộ và sử dụng rsyncnhư bình thường, ví dụ:

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

1
Gắn hệ thống tập tin cục bộ sẽ không lưu bất kỳ băng thông nào giữa nguồn và máy cục bộ. Tuy nhiên, nó sẽ tiết kiệm băng thông giữa cục bộ và đích (vì nó không được gắn cục bộ). Sử dụng rsync theo cách này chỉ có ý nghĩa nếu bạn đang cố gắng tiết kiệm băng thông trên đích.
Kevin Cox
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.