ローカルシェルを使用して2つのリモートホスト間でファイルを転送したいのですが、2つのリモートが次のように指定されている場合、rsyncは同期をサポートしていないようです:
$ rsync -vuar host1:/var/www host2:/var/www
The source and destination cannot both be remote.
同様の結果を得るために使用できる他の回避策/コマンドは何ですか?
ローカルシェルを使用して2つのリモートホスト間でファイルを転送したいのですが、2つのリモートが次のように指定されている場合、rsyncは同期をサポートしていないようです:
$ rsync -vuar host1:/var/www host2:/var/www
The source and destination cannot both be remote.
同様の結果を得るために使用できる他の回避策/コマンドは何ですか?
回答:
発見したように、リモートソースとリモート宛先で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への直接接続はありません。
sshfs
的には、両方のリモートディレクトリをローカルにマウントしrsync
てから、ローカルにマウントされた2つのディレクトリで使用しました。
-i
sshコマンドに必要なキーを指定する方法を理解するのに苦労しています。
-i key...
は、ssh
コマンドの後に引用符内にパラメーターを追加します。それが役に立たない場合は、コンテキストにこの答えを参照して、新しい質問をお気軽にお尋ねください
scp -3
。
あるホストにログインしてから別のホストにコピーしたくない理由を言わなかったので、私の理由と解決策の1つを共有します。
どちらのホストにも他方にログインできるSSHキーがないため、一方のマシンにログインしてからもう一方のマシンにrsyncできませんでした。ログイン中に最初のホストがSSHキーを使用できるように、SSHエージェント転送を使用してこれを解決しました。
警告: SSH転送により、ホストはログイン中にSSHキーを使用できます。キーをコピーすることはできませんが、キーを使用して他のマシンにログインすることはできます。リスクを理解し、信頼できないマシンにはエージェント転送を使用しないでください。
次のコマンドは、SSHエージェント転送を使用して、からhost1
への直接接続を開きhost2
ます。これには、コマンドを実行しているマシンが転送のボトルネックにならないという利点があります。
ssh -A host1 rsync -vuar /var/www host2:/var/www
-D
ではなく、ポート転送を使用します-A
)。利点を説明するため。コマンドが短いため。そして、実際に機能しています。username@host1
ローカルのユーザー名と異なるかどうかを指定する必要がある場合があることに注意してください。また、rsyncはhost2への接続時にホストキーの検証を実行するため、host1のキーはすでにhost2の〜/ .ssh / known_hostsに存在する必要があります。そうでない場合、コマンドは失敗します。
ssh -A
参照してください。 jetbrains.com/display/TCD10/SSH+Agent)。
私はロアイマの答えが好きですが、パスは両方の例で同じであり、どちらがどちらかわかりません。以下が機能しないことを確認しました。
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のターゲットで開始されます。(コメントで説明を求めることができます。)
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"
理想的な方法は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)をご覧ください。私はそれを使用し、それが役立つことがわかりました。
追加情報として:
ジャンプホストを使用して他の2つのマシンを接続しても、お互いに直接到達できない場合、次のように(ジャンプホストで)これら2つのマシン間でsshfsを媒体として使用できます。
$ mkdir ~/sourcepath ~/destpath
$ sshfs sourcehost:/target/dir ~/sourcepath
$ sshfs desthost:/target/dir ~/destpath
$ rsync -vua ~/sourcepath ~/desthpath
SSHFSはジャンプホスト上に2つのパスを提供し、rsyncは通常のようにファイルの同期を管理します(仮想的にローカルで行われるという違いがあります)。
使いやすいスクリプト
長年にわたり、私はこれを他のすべての回答とほぼ同じトリックで何度も行いました。ただし、詳細を間違えたり、問題を解明するのに多くの時間を費やすことは非常に簡単なので、その下のスクリプトを思いつきました。
ssh -A
認証データの伝播に失敗した場合の回避策(回避策は根本原因を見つけるより簡単だったため、なぜこれが起こるのかわからない)スクリプトの使用方法
使い方
私が言ったように、他のすべての答えと同じトリックを使用しています:
-R
localhostからhost1にsshするsshのオプションと同時に、host1がlocalhost経由でhost2に接続できるようにするポート転送を設定する(-R localhost:$FREE_PORT:$TARGET_ADDR_PORT
)-A
2番目の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
転送では再起動と増分転送が処理されます。
tar
via を使用しssh
てファイルを転送することができます:
ssh -n user1@host1 'tar jcf - -C /var/www .' | ssh user2@host2 'tar jxvf - -C /var/www'
の代わりにを使用してアーカイブを圧縮する場合は、j
パラメータ(for tar
)をz
2つの場所に変更します。通常、圧縮率はの場合よりも高くなりますが、処理速度は遅くなります。必要に応じて変更してください(bzip2とgzipを参照)。gzip
bzip2
bzip2
gzip
関連:ファイアウォールの背後にあるときにリモートサーバーからSSHにパイプされたtarを使用して、2つのリモートホスト間でコピーする方法は?
あるいは、透過的な圧縮のために帯域幅を安全にするために、sshfs
リモートファイルシステムをローカルとしてマウントしrsync
、通常どおり使用することができます。
$ sshfs user1@host1:/var/www /mnt
$ rsync -vuar /mnt user2@host2:/var/www