なぜscpの代わりにrsyncコマンドを使うのか?

なぜ rsyncコマンドを 使うのか?

これまでサーバ間のファイルコピーはscpを利用してきました。しかし、scpは時代遅れだという指摘を知り合いから頂きました。今回はscpに代わるrsyncコマンドについてまとめてみます。

rsyncコマンドの最も良い点は、差分コピーが可能であることだと思います。余分なコピーが発生しないため、処理を高速化できるのはうれしいですよね。

rsyncの基本的な使い方と、気を付けるべきポイントについてまとめます。

scpとrsync

OpenSSH8.0において、scpのような古いプロトコルではなく、sftpやrsyncといった近代的なプロトコルを利用することを推奨しています。

The scp protocol is outdated, inflexible and not readily fixed. We recommend the use of more modern protocols like sftp and rsync for file transfer instead.

https://www.openssh.com/txt/release-8.0, Security

正直、OpenSSHが推奨している程度ならこのままscpで良いかなと思ったのですが、rsyncにはscpにない機能がデフォルトで搭載されています。

その機能が、変更があったファイルのみをコピーするという差分コピーです。バックアップやサーバからデータを取得するときに便利ですよね。

rsyncの例とよく使う3つのオプション

rsyncの使い方は下記です。scpとほぼ同じです。

$ rsync [OPTION]... SRC [SRC]... DEST
# ローカルでのコピーの例
$ rsync -r dirA/ dirB/
# サーバからローカルへのコピー例
$ rsync -av username@hostname:/path/to/hoge/ /local/path

rsyncでよく利用するであろう3つのオプションです。

オプション内容
-v, –verbose進行状況の出力
-a, –archiveアーカイブモードで実行
-c, –checksumchecksumを利用した差分の検出

-vオプションはわかると思うので、-aと-cについて下記で説明します。

アーカイブモードとは(-a)

アーカイブモードとは他の主要なオプションを組み合わせたモードのことです。

アーカイブモードでは下記が有効になり、”-rlptgoD”オプションを指定することと同じ効果になります。

  • ディレクトリを再帰的に処理
  • シンボリックリンクはシンボリックリンクとしてコピー
  • パーミッション、タイムスタンプ、所有者・所有グループを保持
  • デバイスファイルと特殊ファイルを保持

つまり下記コマンドによりディレクトリdirAをディレクトリdirBにコピーすることができます。

$ rsync -a dirA/ dirB/

チェックサムchecksumとは(-c)

checksumとは、送信元と送信先のファイルが同じかどうかをファイルサイズに基づいて調べる機能です。また、128bitで表現される数値のことを表すときもあります。

rsyncでは、送信元と送信先のファイルが同一であるかどうかを判断してから、異なるファイルのみをコピーします。

同一であるかどうかを判断するために、デフォルトでは”quick check”と呼ばれる方法が利用されますが、-cオプションを利用することで”checksum”と呼ばれる方法に変更可能です。

quick checkでは、タイムスタンプとファイルサイズに基づいて2つのファイルが同じであるかをチェックします。

一方で、checksumではファイルサイズが同じものに対して、128bitのchecksumと呼ばれる数値を計算し、それに基づいて2つのファイルが同じであることをチェックします。

checksumの算出は送信元と送信先の両方で行われるため、-cオプションを付与するとrsyncコマンドは遅くなります。一方で、quick checkより厳しくファイルのチェックが行われることになるので、もしかしたらコピーするファイル数を減らすことができるかもしれません(送信元と送信先でタイムスタンプが異なるけどファイルの内容は同じ場合など)。

ディレクトリをコピーするときに気を付けるべきこと

rsyncでディレクトリをコピーするときには注意が必要です。

送信元の指定方法によって、ディレクトリごとコピーされるか、ディレクトリの中身がコピーされるかが異なります。ポイントは、ディレクトリ名の後にスラッシュ”/”を追加するかどうかです。

この挙動の違いは十分に注意が必要です。

ディレクトリの中身がコピーされる(スラッシュあり)

$ ls -R
./testA:
sample.txt
$ rsync -r testA/ testB/
$ ls -R
./testA:
sample.txt
./testB:
sample.txt

ディレクトリごとコピーされる(スラッシュなし)

$ ls -R
./testA:
sample.txt
$ rsync -r testA testC/
./testA:
sample.txt
./testC:
testA/
./testC/testA:
sample.txt