【rsync】差分同期バックアップの仕組みと使い方~リモート接続のプロトコルポートやオプション~

スポンサーリンク
スポンサーリンク

rsync のアルゴリズム ~単純コピーのcp/scpコマンドとはどのように違うのか?~

rsyncは元々は『低速回線を使って高速にファイルを転送・同期する仕組み』として生まれました。そのアルゴリズムはこの目的に対して極めて優れており、1996年に Andrew Tridgell と Paul Mackerras に発表されて以来、今までに広く使われています。

現在のrsyncコマンドは以下のアルゴリズムで動作します。

1. コピー元からコピー先へのファイルリストの提示

コピー元はコピー先に対し、コピー対象の「ファイル名」「タイムスタンプ」「ファイルサイズ」の3つの情報を記載したファイルリストを提示します。

rsyncを実行したサーバがファイルコピー先の場合は "receiving incremental file list"、コピー元の場合は"sending incremental file list"と表示されますが、それがこのフェーズです。

2. コピー先がファイルリストを3つに分類

コピー先はコピー元から受信したファイルリストを以下のように分類します。

①同一ファイル

3つの情報が全て一致した場合は「同一ファイル」と見做し、コピー不要の旨を返信します。

②存在しないファイル

ファイル名がコピー先に無い場合、「存在しないファイル」として、コピーが必要な旨を返信します。

③差分がありそうなファイル

ファイル名が同じだけどタイムスタンプもしくはファイルサイズが異なるファイルについては、そのファイルを"chunk(チャンク)"という単位(2018年現在は32KB *1)に小間切れにし、chunk単位で"rolling checksum"という簡易なハッシュ値と、より強力なハッシュ関数(もともとはmd4, 2007年からmd5 *2)値を計算をして順次コピー元に送ります。

*1 https://github.com/AndyA/rsync/blob/master/rsync.h

*2 https://github.com/AndyA/rsync/commit/a0456b9c4635be8832fc5712454a75ec102b1176

なお、3つの情報だけの場合、例えばたまたまタイムスタンプとサイズが同じだが中身が異なるファイルになってしまった場合(例えばコピー元とコピー先で同時に同じ1文字だけ変更した場合等)は通常は検知できません。-cオプションを使えば、このファイル分類のときに3つの情報に加え、チェックサムも見ることができ、検知できます(当然負荷が上がりコピー速度は遅くなります)。

rsync -c /etc/chrony.conf  user1@192.168.1.1:/backup/settings/chrony.conf

3. コピー元からコピー先へファイル転送

「2-①同一ファイル」についてはコピーを実行せずスキップし、「2-②存在しないファイル」については丸ごとコピーを実行します。

「2-③差分がありそうなファイル」についてはコピー元でも同様に chunk毎に "rolling checksum" を計算し、受信した rolling checksumと差異を確認します。もし差異があればすぐ様そのchunk分だけコピー先へ転送します。もしrolling checksumに差異が無い場合、本当に一致していないかを確認するために、より強力なハッシュ関数で確認します。そこで差異があればやはりchunk分のみ転送しますし、差異がなければ転送しません。

このように、ファイル全体をコピーするのではなく、ファイルの中でも一致する部分が多ければそれだけコピー量(つまりネットワーク転送量)を減らすことができます。

この事実から、rsyncが本領を発揮するのは「低速回線を跨ぐ同期」かつ「ファイル数は少ないが大容量ファイルの割合が多い」かつ「コピー元とコピー先で差分が少ない」ケースです。

逆にrsyncが遅くなるのは「(高速だが)遅延の大きい回線(WAN回線等)を跨ぐ同期」または「ファイル数が多く、小容量ファイルの割合が多い」または「コピー元とコピー先で差分が大きい」といったケースです。このようなケースでは、その用途がバックアップなのであれば(ファイルシステムを意識しない)ボリューム単位でのバックアップデータを転送する方式も検討に入れた方がよいでしょう。

スポンサーリンク

プロトコルは rsync?ssh?

rsyncコマンドの構文は以下の通り単純です。

rsync [Options] [Src File or Directory] [Dst File or Directory]

ですがここでややこしいのが、rsyncには2つの方式があることです。1つはrsh(リモートシェル)を使った方式、もう1つはrsyncdを使った方式です。rsh は 具体的にはsshを使うのがデフォルトであり、こちらのほうがよく使われます。この場合、必要なTCPポートはssh のポートであり、rsync のポート tcp:873 は必要ないのです。

rsh(ssh)を使う場合はリモートホストの指定で : (コロン1つ) で区切ります。例えばローカルの/etc 配下全てを 192.168.1.1 ホストの /backup/host-A 配下に同期したい場合は、以下のコマンドを使います。(192.168.1.1 にはuser1というユーザでsshログインできる前提です)

rsync -r /etc user1@192.168.1.1:/backup/host-A

※ -r はディレクトリを下の階層も含め丸ごと(再帰的)にコピーするオプションです。

このコマンドで必要となるポートは TCP:22 になります。

一方、rsyncdを使う場合は::(コロン2つ)もしくはrsync://を使います。

rsync -r /etc user1@192.168.1.1::/backup/host-A
rsync -r /etc rsync://user1@192.168.1.1/backup/host-A

このコマンドで必要となるポートは TCP:873 になります。ただし、これ以外にも /etc/rsync.conf の設定等が必要ですので、ssh が使えるのであれば、わざわざこれらの設定をしなくとも ssh の方式を使えば良いでしょう。

また、セキュリティのために ssh でポートを変更していたり公開鍵認証を使っている場合もあるかと思います。例えばtcpポート22222を利用し、秘密鍵を /home/user1/.ssh/id_rsa に配置している場合は以下のコマンドを使います。

rsync -r -e "ssh -p 22222 -i /home/user1/.ssh/id_rsa" /etc user1@192.168.1.1:/backup/host-A

スポンサーリンク

オプション

標準系は以下です。

rsync -av /etc user1@192.168.1.1:/backup/host-A

目的・シチュエーションに応じてオプションを付け加えます。

-a (–archive)

-r, -l, -p, -t, -o, -g, –devices, –specialsの8つのオプションを同時に指定したのと同義。

-u (–update)

このオプションが無い場合、前述の通り、"タイムスタンプ"もしくは"サイズ"が異なればコピーされるが、このオプションがある場合は、"コピー元のタイムスタンプがコピー先よりも新しい"場合にコピーされる。

-v (–verbose)

コピーしたファイル名やバイト数などの転送詳細情報を表示する。

-r (–recursive)

指定パスのファイルだけでなく、その配下にあるディレクトリおよびファイルを全てコピーする。

-l (–links)

シンボリックリンクをシンボリックリンクのままコピーする。

-p (–perms)

パーミッションをコピーする。ただし、SELINUXのコンテキスト情報は含まれないので注意

-t (–times)

タイムスタンプ情報をコピーする。

-o (–owner)

ファイル所有者情報をコピーする。

-g (–group)

ファイルグループ情報をコピーする。

–devices

ブロックデバイスは、(ファイル単位ではなく)ブロックデータのままコピーする。

–specials

名前付きパイプ等の特殊ファイルをコピーする。

--delete

コピー元に存在しないファイルが、コピー先に存在する場合、コピー先のそのファイルを削除する(コピー元とコピー先を完全一致させる)。

-S

スパースファイルをスパースのままコピーする。

-n

実際にはコピーせず、コピーした時と同じ出力を表示させる(動作確認用, dry run.)

-b

もしコピー先で上書きや削除される条件に該当した場合、そのファイルを消さずにリネームする。デフォルトでは同一ディレクトリ内で、ファイル名の最後に~を付ける。

--backup-dir=[dir]

-b でリネームする際に、指定したディレクトリ [dir] に mv する。

--suffix=[suffix]

-b でリネームする際に、~ではなく [suffix] を付ける。

--exclude=[pattern]

コピー対象から除外する。例えば --exclude='*.old' と指定すれば .old のファイル/ディレクトリをコピーしない。(-r を使っている場合、下位のディレクトリにも効果あり)

--bwlimit=[rate]

速度制限する。例えば --bwlimit=1.5m と指定すれば1.5M Byte/sec となる。

スポンサーリンク
スポンサーリンク
スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
スポンサーリンク