2つのリモート間でファイルをrsyncする方法は?


54

ローカルシェルを使用して2つのリモートホスト間でファイルを転送したいのですが、2つのリモートが次のように指定されている場合、rsyncは同期をサポートしていないようです:

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

同様の結果を得るために使用できる他の回避策/コマンドは何ですか?



1
実際、3番目のホストでsshfsを活用することにより、2つのリモートホスト間でrsyncを実行できます。sshfsを使用してhost1とhost2をホスト3にマウントします。その後、1と2の間でrsyncを実行します。
William Legg

使用と@WilliamLegg欠点はsshfs、そのされrsync、その差分アルゴリズムを無効にして、両方のローカルとしてソースおよび宛先ファイルシステムを見ています。その時点でを使用することもできますcp -pこれとその後のコメントを提案する回答を参照してください。
ロアイマ

回答:


50

発見したように、リモートソースとリモート宛先でrsyncを使用することはできません。2つのサーバーが互いに直接通信できないと仮定すると、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オプションは(ローカルマシンを介して)host1のポート50000からhost2のポート22にマップするリバースチャネルを設定します。host1からhost2への直接接続はありません。


1
@roaimaのソリューションは気に入っていますが、さまざまな理由で機能しませんでした。最終sshfs的には、両方のリモートディレクトリをローカルにマウントしrsyncてから、ローカルにマウントされた2つのディレクトリで使用しました。
aidan

キーが使用されている例を見ることができますか?-isshコマンドに必要なキーを指定する方法を理解するのに苦労しています。
-onassar

@onassar -i key...は、sshコマンドの後に引用符内にパラメーターを追加します。それが役に立たない場合は、コンテキストにこの答えを参照して、新しい質問をお気軽にお尋ねください
。roaima

1
逆接続は、ローカル側の〜/ .ssh / configに情報を読み取ることはありません-何のSSHの設定ファイルがなかったかのように解決することができるものを使用する必要性
フィレンツェKley

1
「2つのサーバーが互いに直接通信できないと仮定します」。このソリューションは、直接のSSH 接続を妨げるファイアウォールまたはNATの問題を回避します。ただし、セキュリティ上の理由で(host1上の)ソースユーザーがキーまたは資格情報を持たない場合、または宛先に対する書き込み権限が不十分である場合には対応していません。それについては、Kevin Coxのソリューションを参照するか、スクリプトまたはを使用した間接接続に頼ってくださいscp -3
セドリックナイト

22

あるホストにログインしてから別のホストにコピーしたくない理由を言わなかったので、私の理由と解決策の1つを共有します。

どちらのホストにも他方にログインできるSSHキーがないため、一方のマシンにログインしてからもう一方のマシンにrsyncできませんでした。ログイン中に最初のホストがSSHキーを使用できるように、SSHエージェント転送を使用してこれを解決しました。

警告: SSH転送により、ホストはログイン中にSSHキーを使用できます。キーをコピーすることはできませんが、キーを使用して他のマシンにログインすることはできます。リスクを理解し、信頼できないマシンにはエージェント転送を使用しないでください。

次のコマンドは、SSHエージェント転送を使用して、からhost1への直接接続を開きhost2ます。これには、コマンドを実行しているマシンが転送のボトルネックにならないという利点があります。

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

3
有効なユースケースを説明するための+1(host1のリモートユーザーが移行先サーバーに対するアクセス許可を持たない場合); 重要なセキュリティ上の注意(キーの制限ではなくネットワークを回避するの-Dではなく、ポート転送を使用します-A)。利点を説明するため。コマンドが短いため。そして、実際に機能しています。username@host1ローカルのユーザー名と異なるかどうかを指定する必要がある場合があることに注意してください。また、rsyncはhost2への接続時にホストキーの検証を実行するため、host1のキーはすでにhost2の〜/ .ssh / known_hostsに存在する必要があります。そうでない場合、コマンドは失敗します。
セドリックナイト

驚異的な答え、これは私が以前にできなかったTeamCityのいくつかのことを調整するのに役立ちました(他のTeamCityユーザーの場合は、使用する前に「SSHエージェント」と呼ばれる「ビルド機能」をビルド構成に追加する必要があります、confluenceをssh -A参照してください。 jetbrains.com/display/TCD10/SSH+Agent)。
ジョンツウィンク

12

私はロアイマの答えが好きですが、パスは両方の例で同じであり、どちらがどちらかわかりません。以下が機能しないことを確認しました。

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

しかし、これは-Rデフォルトですので、オプションからlocalhostの明示的なbind_addressを省略しました:

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

2つのリモートホスト間でsshキーを正しく設定し、host1に秘密キーを、host2に公開キーを設定する必要があることに注意してください。

接続をデバッグするには、これを2つの部分に分けて詳細ステータスを追加します。

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

これが機能する場合、host1にシェルがあります。ここで、host1からrsyncコマンドを試してください。これを別のウィンドウで行うことをお勧めします。これにより、詳細なssh情報がrsyncステータス情報と混同されないようになります。

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

私の例では、パスはソース、宛先です。これrsyncは、host1で開始され、host2のターゲットで開始されます。(コメントで説明を求めることができます。)
ロアイマ

1
私はコメントしたでしょうが、50 +以上の評判がなければ他の誰かの投稿にコメントすることはできません。
jaybrau

7

bashスクリプト構文でroaimaによる回答の再フォーマット(および明確にするために行継続文字「\」を追加)ポート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.

次回は、他の人の回答を編集して直接改善してください。
ロアイマ

この答えは、ssh-agent転送(-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

追加情報として:

ジャンプホストを使用して他の2つのマシンを接続しても、お互いに直接到達できない場合、次のように(ジャンプホストで)これら2つのマシン間でsshfsを媒体として使用できます。

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

SSHFSはジャンプホスト上に2つのパスを提供し、rsyncは通常のようにファイルの同期を管理します(仮想的にローカルで行われるという違いがあります)。


1
パフォーマンスはひどいことに注意してください。これは、変更を検出するために、rsyncがソースサーバーからファイルを読み取り、ネットワーク全体を転送するためです。直接転送できない場合は、rsyncを使用している場合はこれを食べる必要があります。また、宛先をマウントしないでください。これは不要であり、ローカルディスクと通信していると見なされるため、rsyncがいくつかのデフォルトを変更します。
ケビンコックス

0

いずれかのコンピューターでrsyncd(サーバー)を実行できます。

これは私が取っているアプローチです。なぜなら、sshを使用して「ソース」(rsyncの言葉遣いで)「パスワード」なしで「宛先」へのアクセスを許可しないためです(rsyncでSSHトンネリングを使用するために必要です)スクリプト)

私の場合、ソースPCから許可された1人のユーザーがソース側からrsyncを使用して、宛先コンピューターにrsyncdサーバーをセットアップするだけです。

よく働く。


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から両方のホストにsshできることを確認してください。
  2. スクリプトの最初の数行で変数を設定します
  3. 実行してください。

使い方

私が言ったように、他のすべての答えと同じトリックを使用しています:

  • -Rlocalhostからhost1にsshするsshのオプションと同時に、host1がlocalhost経由でhost2に接続できるようにするポート転送を設定する(-R localhost:$FREE_PORT:$TARGET_ADDR_PORT
  • -A2番目のsshシャネルの簡単な認証を可能にする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転送では再起動と増分転送が処理されます。
ロアイマ

1
もちろん@roaima-私はtarに相当するものとは考えていません。rsyncが100%必要ではないという問題を解決するためにこれを読む日のために、この合格基準を残しました。
ndemou

-1

tarvia を使用しsshてファイルを転送することができます:

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

の代わりにを使用してアーカイブを圧縮する場合は、jパラメータ(for tar)をz2つの場所に変更します。通常、圧縮率はの場合よりも高くなりますが、処理速度は遅くなります。必要に応じて変更してください(bzip2とgzipを参照)。gzipbzip2bzip2gzip

関連:ファイアウォールの背後にあるときにリモートサーバーからSSHにパイプされたtarを使用して、2つのリモートホスト間でコピーする方法は?


あるいは、透過的な圧縮のために帯域幅を安全にするために、sshfsリモートファイルシステムをローカルとしてマウントしrsync、通常どおり使用することができます。

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

1
ファイルシステムをローカルにマウントすると、ソースマシンとローカルマシン間の帯域幅が節約されません。それはされます(それがローカルにマウントされていないとして)しかし、ローカルと宛先の間の帯域幅を節約します。この方法でrsyncを使用するのは、宛先の帯域幅を節約しようとしている場合にのみ意味があります。
ケビンコックス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.