scp と rsync
あるファイルをリモートホストAに転送したいけれど、セキュリティの配慮などNWの都合上で一旦踏み台ホストBを経由する必要があるケースは多いと思います。通常scp か rsyncコマンドを使うかと思いますが、今回はその方法についてまとめたいと思います。
scp
scp はまず真っ先に思い付くであろうコマンドです。ssh接続による通信データを暗号化しながらコピーが可能です。
$ scp 【ローカルファイルパス】 【踏み台ホストユーザ】@【踏み台ホスト】:【踏み台ホスト格納ディレクトリパス】
$ ssh 【踏み台ホストユーザ】@【踏み台ホスト】
$ scp 【踏み台ホストファイルパス】 【リモートホストユーザ】@【リモートホスト】:【リモートホスト格納ディレクトリパス】
scp を用いた上記の方法のデメリットは目的のリモートホストへファイルを送る前に、踏み台にファイルを送るという手間があることと、踏み台に余計なファイルを生成するという事です。
踏み台は各ユーザに最低限のリソースしか割かない場合が多いので、OSのイメージファイルなど大きなファイルを転送する時などは、サーバのディスク容量が足りずファイルが破損する可能性があります。※自分は破損したことがあります
scp を使ったもう一つの方法を見てみます。scp
コマンドにオプションを付与することで踏み台にファイルを残さずにリモートホストへ転送する方法です。
$ scp -o "ProxyCommand ssh 【踏み台ホストユーザ】@【踏み台ホスト】 -W %h:%p" 【ローカルファイルパス】 【リモートホストユーザ】@【リモートホスト】:【リモートホスト格納ディレクトリパス】
例
$ scp -o "ProxyCommand ssh -i .ssh/id_rsa juser@xxx.xxx.xxx.xxx -p 2222 -W %h:%p" ./file ruser@yyy.yyy.yyy.yyy:/root/
scp -o
- オプション付与
ssh -W %h:%p
- -W
- 標準入力/出力を後続のホスト/ポートに転送する
- %h:%p
- 【リモートホスト】:【リモートポート】
- -W
上記の場合でもまだデメリットがあります。scp
は転送の際に一時ファイルを作成せずにファイルを転送するため、転送中にファイルにアクセスしたり転送を止めたりするとファイルが破損する可能性があります。途中ネットワークが輻輳して回線が途切れてしまった場合は再度最初から転送し直す必要があります。
rsync
rsync を使用するとこれまでの問題を全て解決出来ます。rsync
コマンドはリモートホストと同期を取りながら、踏み台経由でファイルを転送することが可能です。またrsync
は一時ファイルを作成し、チェックサムをとることでホスト間で差分確認をしながらファイル転送を行います。そのため仮に中断しても途中から転送を再開することが出来る上に、ファイルが破損しません。rsync
は特にディレクトリ単位で同期を行うために用いられることの多いコマンドです。
まずは踏み台を介さない構成でrsync の基本的な使い方について見ていきます。
$ rsync -avz 【ローカルファイルパス】 【リモートホスト名】:【リモートホストパス】
- -a:
- アーカイブモード。所有者やシンボリックリンクなどの情報を出来るだけそのままで転送する。(
-rlptgoD
指定と同義)
- アーカイブモード。所有者やシンボリックリンクなどの情報を出来るだけそのままで転送する。(
- -v:
- 饒舌モード。
- -z:
- 転送前にデータを圧縮し転送後にデータを解凍する。圧縮前後でサイズが変わらない場合はオーバーヘッドのみ増える事になる。
踏み台を経由する場合のrsync
コマンドの使い方は以下の通りです。なお基本的に.ssh/config
にまとめた方が見やすくて管理も楽なのでその例を記載します。コンフィグの書き方や詳細情報はこちらを参考にして下さい。
$ cat .ssh/config
Host rsyncJmp
User juser
Hostname xxx.xxx.xxx.xxx
port 2222
IdentityFile ~/.ssh/id_rsa
Host rsyncHost
Hostname yyy.yyy.yyy.yyy
User ruser
ProxyCommand ssh rsyncJmp -W %h:%p
$ rsync -av ./file rsyncHost:/root/
また中断されることを想定したコマンドは以下の通りです。
$ rsync -av --append ./file rsyncHost:/root/
--append
オプションを付与すれば差分を確認して途中から転送を行うことが出来ます。但し注意すべき点があります。転送元ファイルが転送先ファイルよりも小さい場合は転送をしない、追記するか否かはファイルサイズを元に判定していること。
つまりrsync
は転送先のファイルサイズを見て同期を行うので、リモートホストの転送済みのデータに対して変更を加えた場合、変更を加えた部分は反映されないのでファイルの内容が想定した物と異なる可能性があるということです。(通常この様なケースは稀かと思いますが)
転送するデータに変更した覚えがある時は--checksum
オプションを付けてデータ差分のあるファイルを同期するようにします。
終わりに
rsync
に比べてscp
は差分を比較しない分処理が早いというメリットがあります。小さいファイルはscp
で、大きいファイルはrsync
で転送するというのが一般的な棲み分けてとなっている模様です。
蛇足
今まで使っていませんでしたが、scp
は.ssh/config
を簡単に利用出来ます。
$ ssh 【configで定義したHostname】:【リモートホストファイルパス】 ./
上記の様な感じで実行可能です。
蛇足2(私的メモ)
rsync
やはり便利です。先日大量のファイルをコピーしていたのですが、cp
だとPCがクラッシュしてしまい永遠に終わらないなーと困っていました。以前に書いたこの記事を思い出して久々にrsync
コマンドによるファイルコピーをしていますが、レジューム機能があるので、クラッシュしても途中から再開出来るので確実です。
$ rsync -av bk/images/contents/ app/public/images/contents
※第二引数の「/」は不要
-a
-rlptgoD
と同義-r
- ディレクトリを再帰的にコピー
-l
- シンボリックリンクをシンボリックリンクのままコピー
-p
- パーミッションを変更せずにコピー
-t
- タイムスタンプを変更せずにコピー
-g
- 所有グループを変更せずにコピー
-o
- 所有者を変更せずにコピー
-D
- デバイスファイルや特殊ファイルを変更せずにコピー
-v
- verbose出力