rsyncだけで実現する!ファイルのバックアップ手法6選 【コマンド例編】

ハードディスクのイメージ

ファイルのバックアップは、サーバー(もちろんクライアントPCでも)を運用するうえで必要不可欠なものです。Linux環境で使えるバックアップツールは様々なものがありますが、そのなかでもrsyncは汎用性が高く、広く使われています。

この記事では、実際に様々な方法でファイルをバックアップするコマンド例を紹介します。

各バックアップ手法に関する特徴やメリット・デメリットは、rsyncだけで実現する!ファイルのバックアップ手法6選 【バックアップ基礎知識編】を参照してください。

rsyncコマンドリファレンス

この記事のコマンド例や解説では、バックアップ元やバックアップ先として以下のディレクトリ・ファイルが存在しているものとします。

バックアップ元:/test/src

バックアップ先:/test/dst

$ tree /test
/test
├── dst
└── src
    ├── image.png
    ├── script.sh
    └── text

書式

rsync [オプション] 転送元パス [転送先パス]

[ ]内は省略可能です。

転送元/転送先パスには、絶対パスもしくは相対パスが使用できます。

よく使われるオプション

オプション 説明
-a アーカイブモード。なるべく転送元ディレクトリの内容を維持したままコピーする。(具体的には、ディレクトリ・シンボリックリンク・パーミッション・タイムスタンプ・所有者・グループ・特殊ファイルをそのまま保持する)
-v 実際に転送されたファイルのリストや、転送量などの統計情報を表示する
-h 表示される情報に適切な単位をつける
-n 実際にファイル転送を行わない。-v と組み合わせると、指定したコマンドでどのようにファイル転送が行われるかの統計情報のみを表示する。コマンドのテストに便利。
-z ファイルを圧縮して転送する。ネットワーク越しの転送に便利。

転送元パスの指定方法

転送元パスがディレクトリの場合、最後に /(スラッシュ)を付けるか付けないかで挙動が変わります。

 

スラッシュを付けない場合、パスに指定されたディレクトリごとコピーします。

$ rsync -a /test/src /test/dst

$ tree /test/dst
/test/dst
└── src
    ├── image.png
    ├── script.sh
    └── text

 

スラッシュを付けた場合、パスに指定されたディレクトリ配下のファイルやディレクトリをコピーします。

$ rsync -a /test/src/ /test/dst

$ tree /test/dst
/test/dst
├── image.png
├── script.sh
└── text

コマンド例

フルバックアップ+増分バックアップ(世代管理なし)

同じコマンドで実装できます。

$ rsync -avh /test/src/ /test/dst

1回目のバックアップは、転送元に存在するファイル・ディレクトリをすべて転送先へバックアップします。(=フルバックアップ)

2回目以降のバックアップは、前回のバックアップからの変更部分(変更のあったファイルと新規作成されたファイル)のみ転送されます。(=増分バックアップ)

最もお手軽なバックアップ方法ですが、バックアップデータが同じディレクトリにたまっていくこと、転送元で削除されたファイルがいつまでも転送先に残り続けることから、バックアップディレクトリが多少ごちゃつきます。また、世代管理はできないので、増分バックアップで世代管理をしたい場合は、増分バックアップ(世代管理あり)がおすすめです。

ミラーリング

$ rsync -avh --delete /test/src/ /test/dst

–delete オプションを付けることで、転送元にないファイルは転送先からも削除されます。

これにより、転送先は常にバックアップ時点での転送元の状態を反映するようになります。(=ミラーリング)もちろん、前回のバックアップから変更がないファイルは転送されません。

バックアップの世代管理をする必要がない場合はこの手法が最も適していると思います。

逆増分バックアップ

rsync -avh --delete --backup --backup-dir="../backup-$(date +%Y%m%d-%H%M%S)" /test/src/ /test/dst/backup-latest

–delete オプションに加えて –backup オプションを付けることで、–delete によって削除されるファイルをバックアップディレクトリに退避します。ミラーリング+ミラーリングで消えるファイルのバックアップ と考えるとわかりやすいかと思います。

バックアップディレクトリの名前は、–backup-dir で指定することができます。コマンド例では、バックアップ時刻のタイムスタンプをディレクトリ名にするように設定しています。

バックアップディレクトリを転送先ディレクトリよりも1つ上の階層に置いているのがミソです。(同じ階層に置くと面倒なことになります。なぜ面倒になるのかは実際に試してみるのがわかりやすいと思います。)

 

具体的には、以下のような感じでバックアップデータがたまっていきます。きっちりと世代管理ができていることがわかります。

$ tree /test/dst
/test/dst
├── backup-20181206-040000
│   └── #2018年12月6日のミラーリングによって削除されたデータ
├── backup-20181207-040000
│   └── #2018年12月7日のミラーリングによって削除されたデータ
└── backup-latest
    └── #最新のバックアップ

差分バックアップ

#初回のバックアップ(フルバックアップ)
$ rsync -avh /test/src/ /test/dst/backup-base

#2回目以降のバックアップ(差分バックアップ)
rsync -avh --compare-dest=../backup-base /test/src/ "/test/dst/backup-$(date +%Y%m%d-%H%M%S)"

–compare-dest オプションで、既存のバックアップのあるディレクトリを指定すると、そのディレクトリと転送元の差分をバックアップすることができます。

コマンド例では、転送先ディレクトリの名前をバックアップ時刻のタイムスタンプにしています。これにより、差分バックアップで世代管理ができます。

 

具体的には、以下のような感じでバックアップデータがたまっていきます。

$ tree /test/dst
/test/dst
├── backup-20181206-040000
│   └── #初回~12月6日の差分
├── backup-20181207-040000
│   └── #初回~12月7日の差分
└── backup-base
    └── #初回のフルバックアップ

実際に差分バックアップをする場合、定期的にフルバックアップをとり直すことが多いと思うので、スクリプトで自動化するにはもう一捻りする必要がありますが…

差分バックアップ(ハードリンク)

#初回のバックアップ(フルバックアップ)
$ rsync -avh /test/src/ /test/dst/backup-base

#2回目以降のバックアップ(差分バックアップ)
rsync -avh --link-dest=../backup-base /test/src/ "/test/dst/backup-$(date +%Y%m%d-%H%M%S)"

–compare-dest の代わりに –link-dest を使うと、2回目以降のバックアップディレクトリには、–link-dest で指定されたディレクトリと転送元の差分がコピーされるほか、–link-dest で指定されたディレクトリ内の変更がなかったファイルへのハードリンクが張られます。

つまり、見た目上は毎回フルバックアップをとっているように見えます。ただし、既存のファイルはハードリンクを張るだけなので、ファイル転送やディスク消費が発生するのは差分のファイルのみになります。

任意の時点のバックアップをすぐにリストアすることができるという点で、優れたバックアップ方法ですが、増分バックアップ(世代管理あり)がこれのほぼ上位互換なので、どうしても差分バックアップしたい場合くらいしか利用シーンが思いつきません。

 

具体的には、以下のような感じでバックアップデータがたまっていきます。

$ tree /test/dst
/test/dst
├── backup-20181206-040000
│   └── #12月6日時点のバックアップ
├── backup-20181207-040000
│   └── #12月7日時点のバックアップ
└── backup-base
    └── #初回のフルバックアップ

増分バックアップ(世代管理あり)

差分バックアップ(ハードリンク)の応用です。

–link-dest が常に1つ前のバックアップを指すようにスクリプトを組んでやると、世代管理ありの増分バックアップを実装できます。

個人的には、世代管理をするならこのバックアップ手法がいちばん汎用性があると思います。

#! /bin/bash

BASEDIR="/test/dst" #バックアップ先の親ディレクトリ
LATESTBKUP=$(ls $BASEDIR | grep backup- | tail -n 1) #直近のバックアップのディレクトリ名

rsync -avh --link-dest="$BASEDIR/$LATESTBKUP" /test/src/ "/test/dst/backup-$(date +%Y%m%d-%H%M%S)"

直近のバックアップは、バックアップ先の親ディレクトリをlsで表示したときの末尾を取得することで指定できます。(コード例4行目)

 

具体的には、以下のような感じでバックアップデータがたまっていきます。

$ tree /test/dst
/test/dst
├── backup-20181205-040000
│   └── #12月5日時点のバックアップ
├── backup-20181206-040000
│   └── #12月6日時点のバックアップ
└── backup-20181207-040000
    └── #12月7日時点のバックアップ

で、結局どれを使うのがいいの?

何か他に特別な要件がなければこうなると思います。(あくまで私個人の見解です)

あわせて読みたい

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です