接続されていない2つのサーバー間でファイルをバウンスするrsyncハック


8

接続は次のとおりです。

[Server1] <---> [my desktop] <---> [Server2]

Server1とserver2は互いに直接対話することはできません(質問しないでください)。しかし、私のデスクトップはssh経由で両方のサーバーにアクセスできます。

server1からserver2にファイルをコピーする必要があります。

伝統的に私はssh + tarハックを次のように使用しています:

ssh -q root@Server1 'tar -vzc /path/to/files ' | ssh -q root@Server2 'tar -vzx -C /'

そして、それはうまくいきますが、私はそれをさらに一歩進めて、私のデスクトップを介して2つのサーバー間でrsyncを動作させたいと思います。

ある端末でsshポートフォワードトンネルを開始してから、別のウィンドウでそのトンネルを介してrsyncを実行できることはわかっていますが、2番目の端末をいじったり、別のポートフォワードトンネルを作ったり壊したりしたくありません。私が欲しいのは:

  • デスクトップを介してServer1からserver2にファイルをrsyncする1つのライナーコマンド
  • すべて1つのコマンドライン、1つのターミナルウィンドウ
  • ポートフォワードトンネルをrsyncコマンドの存続期間のみ存在させたい。
  • scpしたくない、rsyncしたい。

誰かがそれをするためのトリックを持っていますか?

編集:これが作業コマンドです!皆さん、素晴らしい仕事です。1. rsaキーパスには、チルダを使用できません。「/ root /」を使用する必要がありました。2.これが最後のコマンドラインです。

ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"

ブームはダイナマイトに行きます。


これは本当に素晴らしいです。変更する必要があるのは、ホストキーの検証を無効にすることです。TTYless認証用のSSHキーがありますが、サーバーが相互に通信したことがないため、サーバーはホストキーを確認できません。だからそれを無効にするのが最善です:-pまたは-iフラグの後に-o StrictHostKeyChecking = no。
アマラ2014

回答:


5

中間マシンにデータのコピーを保持することに満足している場合は、server1を参照として使用してローカルコピーを更新し、次にローカルコピーを参照として使用してserver2のバックアップを更新するスクリプトを記述するだけです。

#!/bin/sh
rsync user@server1:/path/to/stuff /path/to/loca/copy -a --delete --compress
rsync /path/to/loca/copy user@server2:/path/to/where/stuff/should/go -a --delete --compress

単純なスクリプトを使用するということは、すべてを実行するための単一のコマンドが必要であることを意味します。もちろん、これはデータが機密情報である場合(セキュリティ保護なし)になる可能性があります(あなたやあなたの会社の他の人は、あなたのラップトップにコピーを浮かばせたくないでしょう)。server1がローカルである場合は、後でローカルコピーを削除するだけでかまいません(次回、ローカルLAN経由で再構築するのが簡単になるため)。

サーバーがより効果的に相互に直接通信できるようにトンネルを構築することは、次のように可能であるはずです。

  1. サーバー2で、/ bin / shのコピーを/ usr / local / bin / shforkeepaliveとして作成します。コピーではなくシンボリックリンクを使用すると、セキュリティが/ bin / shにパッチを当てた後に更新する必要がありません。
  2. サーバー2で、数秒間ループスリープしてから少量のテキストをエコー出力するだけのスクリプトを作成し、shの「コピー」を使用するようにします。

    #!/usr/local/bin/shforkeepalive
    while [ "1" != "0" ]; do
            echo Beep!
            sleep 5
    done
    

    echoSSHdがsshクライアントからのキープアライブパケットを無視するように構成されている場合でも、セッションがタイムアウトになるまでアイドル状態にならないため、おそらく必要ありません)

  3. これで、バックグラウンドでリバーストンネルを開始し、rsyncを使用してコピー操作を実行するようにserver1に指示し、ループスクリプト(SSHセッションを閉じる)を終了してリバーストンネルを終了するスクリプトをラップトップに書き込むことができます。

    #!/bin/sh
    ssh user@server2 -L2222:127.0.0.1:22 /usr/local/bin/keepalivesctipt &
    ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'
    ssh user@server2 killall shforkeepalive
    

これが機能する方法:

  • 1行目:標準の「このスクリプトを解釈するために使用するコマンド」マーカー
  • 2行目:リバーストンネルを使用してSSH接続を開始し、それを介してキープアライブスクリプトを実行して開いたままにします。末尾の&はbashにこれをバックグラウンドで実行するように指示し、次の行が完了するのを待たずに実行できるようにします
  • 3行目:上記のトンネルに接続するトンネルを開始して、server1がserver2を認識できるようにし、rsyncを実行してこの配置でコピー/更新を実行します
  • 4行目:rsync操作が完了すると(つまり、2番目のSSH呼び出しが戻ると)キープアライブスクリプトを強制終了します。これにより、最初のsshセッションが終了します。

これは特にきれいには感じられませんが、動作するはずです。私は上記をテストしていないので、調整する必要があるかもしれません。rsyncコマンドをserver1で1行のスクリプトにすることで、呼び出し側のsshコマンドで 'などの文字をエスケープする必要性を減らすことができます。

ところで、あなたは2つのサーバーがお互いを直接見ることができない理由を「尋ねないで」と言いますが、これにはしばしば正当な理由があります。私のホームサーバーとそのオンラインバックアップが保持されているサーバーは互いにログインできません(すべてのユーザーに対して異なるパスワードとキーを持っています)-これは、2つのうちの1つがハッキングされた場合、簡単なルートとして使用できないことを意味しますもう1つをハッキングして、私のオンラインバックアップをより安全にします(ライブから私のデータを悪意のある誰かが削除すると、メインのバックアップサイトに直接アクセスする機能がないため、バックアップを更新してそのバックアップを削除する機能を使用できません)。両方のサーバーはどちらも他の場所にある中間サーバーに接続できます-ライブサーバーは早朝にバックアップを(rsyncを介して)中間マシンにプッシュするように設定され、バックアップサーバーは(しばらくしてから手順1を完了するために)接続するように設定されています更新を収集します(繰り返しますが、rsycを使用し、その後、複数のバックアップ期間を維持するためにスナップショットを作成します)。このテクニックはあなたの状況でも使えるかもしれません。もしそうなら、私はよりクリーンな方法としてそれをお勧めします。

編集:私のハックをアーロンのものとマージして、/ bin / shのコピーとserver2の個別のキープアライブスクリプトによる面倒な作業をすべて回避します。ラップトップのこのスクリプトですべての作業を行うことができます。

#!/bin/sh
ssh user@server2 -L2222:127.0.0.1:22 sleep 60 &
pid=$!
trap "kill $pid" EXIT 
ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

上記と同様に、rsyncはlocalhost:2222に接続しています。これは、トンネルをラップトップのlocalhost:2222に転送し、ラップトップのlocalhost:2222は、他のトンネルを介してserver2のlocalhost:22に転送します。

編集2: server1がserver2で直接認証できるキーを持っていることを気にしない場合(トンネルなしではserver2を認識できない場合でも)、次のようにさらに単純化できます。

#!/bin/sh
ssh user@server1 -R2222:123.123.123:22 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

ここで、123.123.123.123はserver2のパブリックアドレスであり、スクリプトの代わりにコピーと貼り付けのワンライナーとして使用できます。


これは大量のデータ(20 + gb)であり、ローカルに保存するのではなく、同時にストリーミングしたりストリーミングしたりすることを好みます。何も保存せずに自分のPCでデータをストリーミングしたい。あなたは「尋ねないでください」について正しいです、ピタですが、それは正当な理由があります。
2010

プレサエ、元の質問の新しい編集を見る
規制

私の最後の編集(タイムスタンプに従ってコメントの数秒前に投稿されたため、おそらく同時に入力していた)で、探しているワンライナーが得られると思います。
David Spillett、2010

HOORAY !!! できます!1. rsaキーの場合、チルダを使用できません。「/ root /」を使用する必要がありました。2.ここでは、最終的なコマンドラインがあります:ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"
regulatre

こんにちは@David、この素晴らしいハックをありがとう。ただし、それを機能させるには、両方のソリューションを使用して(最初と2番目の編集で)サーバー1にサーバー2のキーが必要です。私はそれは正常だと思います(ポート転送かどうか、server1はまだserver2への認証を試みています)と書きIf you don't mind server1 having a key ...ますが、server2のキーをserver1に置かないようにすることが本当に可能かどうか教えてください。
ssssteffff

2

同期を単純な1行にするいくつかの方法を次に示しますが、いくつかの設定作業が必要です。

  • server1からデスクトップへの逆sshトンネルを設定します(申し訳ありません.ssh/configが、頭の上から呪文を言うことはできません)。デスクトップからserver2への接続でチェーンします。server1からrsyncを実行します。

  • デスクトップにsocksプロキシー(またはCONNECTを受け入れるhttpプロキシー)をセットアップします。これを使用して、server1からserver2へのssh接続を確立します。server2からrsyncを実行します。

  • rsyncの代わりにunisonを使用します。ただし、ワークフローは異なります。

  • sshfsを使用して、デスクトップ上の1つまたは両方のサーバーからディレクトリをマウントします。


1

なぜ1行なのか?小さなシェルスクリプトを使用します。

#!/bin/bash
# Run me on server1

# Create the port forward server1 -> desktop -> server2 (i.e.
# the first forward creates a second tunnel running on the desktop)
ssh -L/-R ... desktop "ssh -L/-R ... server2 sleep 1h" &    
pid=$!

# Kill port forward process on exit and any error
trap "kill $pid" EXIT 

rsync -e ssh /path/to/files/ root@localhost:/path/to/files/on/server2

IIRCでは、スリープ時間を低く設定できます。最初のものsshは、誰かがチャネルを使用している限り終了しません。


私はかなり確信してrsyncはSSHを介して2つのリモート・サーバの間で動作することができないということだそのように(のみローカルから>リモートまたはリモート- >ローカル) -のご利用のにsleepとはtrap私の答えに方法を「キープアライブと殺す」よりも滑らかな印象があります。
David Spillett、2010

元の質問の編集を参照してください。
規制

くそー、あなたは正しい。コマンドリングの引数として2つのホストを指定することはできません。...
hmmm

さて、私は私のソリューションを改善しました。server2のsshサービスをserver1で表示できるようにするには、2つのポート転送を作成する必要があります。
Aaron Digulla 2010

「;」をいくつか追加します それをワンライナーに変える。このアイデアは、スクリプトを使用すると理解しやすくなります。
Aaron Digulla 2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.