rsyncで差分バックアップを行うための「--link-dest」オプションCommand Technica

rsyncはオプションを駆使すれば、差分バックアップも簡単に行えます。今回は前回取り扱わなかった内容も含め、rsync上級者に進むために覚えておきたい「--link-dest」オプションを中心に紹介します。

» 2008年04月25日 10時10分 公開
[前島梓,ITmedia]

 前回は、rsyncにかんする基本的な事項について説明しました。今回は前回取り扱わなかった内容も含め、rsync上級者に進むために覚えておきたい「--link-dest」オプションを中心に紹介したいと思います。なお、本稿でサンプルとして示しているディレクトリ名やアカウント名は前回と同様以下のようにしています。

  • ローカルのバックアップ対象:~/dir1もしくは~/dir2
  • バックアップ先のリモートホスト:xxx.backup.com
  • リモートホスト接続時のアカウント名:backupuser

基本形のおさらいと一部例外

 まずはrsyncコマンドの基本形をおさらいしておきましょう。次のような形でした。

rsync [オプション] コピー元 コピー先

 今回の本題に入る前に、準備体操的に以下は、この基本形から外れた構文です。基本形に従うなら、コピー元が「~/dir1」、コピー先が「~/dir2」となるはずですね。では、「xxx.backup.com:dir/」はどう解釈されるのでしょうか。

$ rsync -av ~/dir1 ~/dir2 backupuser@xxx.backup.com:dir/


 頭で考えるように手が先に動いてしまう方であれば、「-n」オプション(--dry-run)を付加して、実際に試されてみたかもしれませんね。上記の例ではディレクトリ名が分かりやすいので、予想もつく方も多かったかと思いますが、「~/dir1」「~/dir2」がコピー元、「xxx.backup.com:dir/」をコピー先と解釈されます。つまり、コピー元には複数のディレクトリを指定できるのです。

 前回、指定した条件にマッチするファイルやディレクトリをコピー対象から除外する(または除外しない)ためのオプションとして「--exclude」「--include」などを紹介しました。さらに、正規表現を利用すればよりスマートな形で記述することも可能になります。目的に対してどの方法を採るかはユーザーによるところが大きいですが、これらを組み合わせて使えば、コピー元についてはほぼ最小限の労力で指定できるようになるでしょう。

インクリメンタルバックアップを実現する「--link-dest」オプション

 さて、今回の主役である「--link-dest」オプションについて解説していきましょう。

 バックアップを作成すると、当然時間とディスク容量を消費することになります。一般的に、毎日1回ローカルのデータをrsyncでリモートホストにフルバックアップするとすれば、バックアップファイルの削除を行わない限り、1カ月後にはローカルのデータの30倍近いサイズがリモートホストに蓄積されることになります。さらに、その中にはまったく更新されていないデータも存在していることも珍しくありません。

 こうした背景から、一般的なバックアップの運用では、フルバックアップは1週間、もしくは1カ月に1回程度で、それ以外の日は差分のみのバックアップ、いわゆるインクリメンタルバックアップを行うことが多いようです。

 rsyncでインクリメンタルバックアップを行うためのオプションが、「--link-dest」です。--link-destオプションが登場する以前は、「-al」オプションをつけたcpコマンドとrsyncを併用する形で行っていた方も多いのではないでしょうか。

 --link-destは、このオプションで指定したディレクトリ以下とコピー元を比較し、ファイルの所有者、タイムスタンプ、パーミッションなどすべてが一致するファイルであれば、指定されたディレクトリ内のファイルのハードリンクを作成します(ファイルが一致しない場合は、ハードリンクではなくコピーが行われます)。ハードリンクを利用すると、重複するデータが存在する場合はディスク容量を消費せずにすみますので、複数のスナップショットを効率よく残すことが可能となります。

 実際の流れで説明してみます。まず、rsyncを実行して最初のバックアップを行います。ここでは、確認のためdir1ディレクトリの下に1つダミーファイル(inode_test)を作ってからバックアップを行っています。

$ touch ./dir1/inode_test

$ rsync -av --delete ~/dir1/ ~/dir1_bak0

building file list ... done

created directory dir1_bak0

./

inode_test


 次に、--link-destにこのdir1_backup/を指定し、差分バックアップを行います(コピー先はdir1_bak2とします)。--link-destの利用で特に注意が必要なのは、--link-destで指定するディレクトリは、コピー先ディレクトリからの相対パスで指定する必要があるということです。今回のケースですと、inode_testには何も変更が加えられていないため、inode_testはハードリンクとなるはずです。

$ rsync -av --delete --link-dest=../dir1_bak0 ~/dir1/ ~/dir1_bak1

building file list ... done

created directory dir1_bak1

./

$ ls -li dir1

23452843 -rw-rw-r-- 1 user group 0 xxxx-xx-xx xx:xx inode_test

$ ls -li dir1_bak0

23452847 -rw-rw-r-- 2 user group 0 xxxx-xx-xx xx:xx inode_test

$ ls -li dir1_bak1

23452847 -rw-rw-r-- 2 user group 0 xxxx-xx-xx xx:xx inode_test


 dir1_bakとdir1_bak2の中に入っているinode_testはinodeも同じで、リンク数も2、つまりハードリンクとなっていることが分かります。

 難しい話になりましたが、例えば以下のような運用をすることで、ディスクの使用量を抑えつつ、複数のスナップショットをとることが可能となります。

$ rsync -av --delete ~/dir1/ dir1_bak0

$ mv dir1_bak0 dir1_bak1 <- 前回のアーカイブファイルを別名保存

$ rsync -av --delete --link-dest=../dir1_bak1 dir1/ dir1_bak0 <- ハードリンクを用いた差分バックアップ(実際には差分というよりはスナップショットです)

$ mv dir1_bak1 dir1_bak2 <- 前回のアーカイブファイルを別名保存

$ mv dir1_bak0 dir1_bak1 <- 前回のアーカイブファイルを別名保存

$ rsync -av --delete --link-dest=../dir1_bak1 dir1/ dir1_bak0 <- ハードリンクを用いた差分バックアップ


 上記の例はナンバリングを手動で作業していますが、実際の運用では、ファイル名に`date +%m%d`をつけるなど、dateコマンドを活用して日付や時刻が分かるようにしておいた方がよいでしょう。あとは、それらをシェルスクリプトとしてcronで一定期間ごとに実行させれば、定期的に自動で実施され、かつ世代管理も行われているバックアップができるようになります。シェルスクリプトを書くに当たってのTipsは別の機会にあらためて紹介したいと思います。

ssh+tarとの違い

 バックアップ/同期という目的を果たすコマンドには、rsyncのほかにも、sshとtarの組み合わせや、セキュリティを考慮しなくてよいのであれば、lftpを使う方法があり(『lftpで行う手軽なバックアップ』参照)、必要に応じて選択することになります。例えば、sshとtarの組み合わせであれば次のようなコマンドでrsyncと同様の処理が可能です。

$ tar zcvf - ~/dir1 | ssh backupuser@xxx.backup.com "tar zpxvf -"


 本稿はrsyncの解説をメインとしていますので、上記コマンドの詳細は解説しませんが、ローカルマシンで~/dir1をtarコマンドでアーカイブ、パイプ(|)を利用することで、sshはそのデータストリームを標準入力として受け取り、接続したリモートホスト側で展開していると理解してください。結果として、「rsync -av ~/dir1 backupuser@xxx.backup.com:~/」と実行した場合とほぼ同じ結果が期待できます。

 1回のみのバックアップであれば、上記の方法とrsyncを比べてもそれほど転送時間に差はでないでしょう。ただし、継続してバックアップを行う場合には、明らかにrsyncを使った方が効率よくバックアップが行えます。これは、rsyncで用いられているアルゴリズムが、2回目以降は更新など変更のあったファイルのみを転送するようになっているからです。例えば、100Gバイトのデータをrsyncでバックアップ/同期する場合、初回にかかった時間が2時間(120分)だったとします。初回のバックアップ後、仮に10%のデータ(10Gバイト)に何らかの変更があったとすると、2回目のrsync実行時にかかる時間は、12分程度になると予想できます。一方、sshとtarの組み合わせによるバックアップでは、基本的に初回と変わらない時間となるでしょう。

 ただし、rsyncではコピー元とコピー先のファイルリストの比較にも時間がかかりますので、上記の予想にその時間を加味して考える必要があります。特に、従来のrsyncでは、まずコピー元のファイルリストをチェックしていたため、コピー元のサイズやファイル数が多くなるほど、転送時間全体に占めるファイルチェックの時間は増えていました。平たくいえば、それほど差分のファイルがない場合でも、なかなか転送がはじまらなかったわけです。これがrsync3系では、差分更新の際、コピー元とコピー先のファイルチェックを同時に行うようになり、パフォーマンスの向上につながっています。これからrsyncを利用しようとする方は、まずお使いのrsyncがバージョン3系であるか確認されることをお勧めします。

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ