Apple 社の Time Machine に似た増分バックアップの仕組みに、さらにリアルタイム性を付加したバックアップシステムについて検討します。用途はホームディレクトリの世代バックアップやサーバ上の重要なデータの保全などです。
思考実験以上・運用レポート以下といったところです、長期の本運用はしていないため何か落とし穴があるかもしれません。
目指すこと
「データのリアルタイムなコピー(レプリカ)をローカルに保全」しつつ、かつそれの「1時間ごとの世代バックアップを作成」することを目指します。
典型的には、ローカルマシンにマウントした外付けディスクや NAS をバックアップ先に指定することになるでしょう。別マシンへ直接バックアップする方法についてものちほど検討しますが、ひとまずローカルディスクに保存し、そのデータをさらに他のサーバへ定期的にコピーする運用を考えます。
- 変更のあったファイルを数秒の遅れで別ディスクに保全する
- 変更のあったファイルの増分のみ保存し容量を節約する
- 容量の大きいファイルや特定のディレクトリを除外する
- 古いバックアップファイルを自動的に消し込む
- Time Machine 風の世代バックアップを行う
- 世代の間隔や数を自由に設計する
- 任意の長期間で保存する(設定上の上限なし)
これらの機能を lsyncd
と rsnapshot
という2つのソフトウェアを組み合わせて実現します。
lsyncd とは
lsyncd (Live Syncing Daemon) は、指定したディレクトリ以下に含まれるファイルを inotify (Linux) や kqueue (BSD) を使ってリアルタイムにウォッチし、更新されたファイルがあれば即時に転送を開始するツール です。分単位のダウンタイムすら許容できない状況に威力を発揮する、攻めのツールと言えます。
デーモンとして常駐し、裏では rsync
を使ってファイルを同期します。データを他のマシンへ転送したり、Amazon S3 に上げることなども可能です。ただし、今回はローカルマシン上のファイルコピーに使います。
なお、動作が若干不安定という話もあるようですから、定期的に再起動したり動作をチェックするような仕組みを導入することを検討するとよさそうです。
rsnapshot とは
rsnapshot は、macOS の Time Machine に似た設計思想に基づいた増分バックアップシステムを実現するためのスクリプトです。
Time Machine の設計とは、まず初回実行時にフルバックアップを取得し、以降は1時間毎に前回から変更されたファイルのみバックアップを取り、30日を過ぎたバックアップは週ごとに1つに間引いて、ディスクの容量がある限りデータを保存する方式です。
スクリプトは Perl で書かれており、mkdir/mv 等の基本的なコマンドと rsync を組み合わせて cron で実行する、シンプルな動作が特長です。バックアップされたそれぞれのファイルはハードリンクとして存在し、変更があったファイルのみ実ファイルとして保持されます。
rdiff-backup との比較
同じような目的のソフトウェアに rdiff-backup がありますが、以下の欠点のため今回は採用しません。
- rsync コマンドを直接呼び出さないので、細かい動作の指定ができない
- 過去のデータを取り出すのにコマンドを実行する必要がある
- 古いデータを消し込むタスクを別途仕込む必要がある
対して rsnapshot
は Unix コマンドを組み合わせて実現しているのでシンプルで分かりやすい作りになっています。問題が起きても調査が容易な点は、安定した長期運用を目指す際に大いにプラスとなります。
環境を構築する
lsyncd をインストールする
yum や brew で入ります。
yum install lsyncd
デーモンとして動作するので、今回は root 権限で起動し、設定ファイルはグローバルのものを使います。
rsnapshot をインストールする
同じく yum や brew で入ります。perl が必要です。
yum install rsnapshot
cron からコマンドを呼び出す形で使用します。今回は各ファイルのオーナーなどの情報を保持したいので root 権限で起動し、設定ファイルはグローバルのものを使います。
監視ファイルの上限を緩和する
Linux では上限数がそれほど多くないので、あらかじめ上限を緩和しておくとよいと思います。/etc/sysctl.conf
に書き込むのも忘れずに。
sysctl -w fs.inotify.max_user_watches=65536
他の OS の対応方法は見つけられませんでした。FreeBSD の kqueue(2) まわりを調べる必要があるかもしれません。情報をお待ちしています。
OS が同時に開けるファイル数もチェックしたほうがよいでしょう。linux なら fs.file-max
、macOS なら kern.maxfiles
や kern.maxfilesperproc
のようです。
システムの構成を設計する
ここでは、ローカルマシンのディレクトリ /app/myproject
以下を、同じくローカルマシンの /mnt/rsnapshot
以下にバックアップすることにしましょう。/mnt
は別のファイルシステム(外付け HDD、NAS 等)をマウントする想定ですが、もちろん同一ディスク上でも(冗長性は下がりますが)運用やテストは可能です。
確保すべき空き容量
初回バックアップ時には、/app/myproject
の2倍の容量が必要です。これは lsyncd
によるリアルタイムバックアップ用の領域 (a) と、rsnapshot
の実ファイル格納用の領域 (b) がそれぞれ別に必要だからです。
- (a) /mnt/rsnapshot/current/
- (b) /mnt/rsnapshot/.sync/
さらに日々の増分の保持に必要となるディスク容量は、どう運用したいかによって大きく変わります。
- どの程度頻繁にファイルを更新するか(また、それらのファイル容量)
- データを何ヶ月・何年くらい保持したいか
もしあまりデータを更新しないのであれば 1.5 倍程度あればひとまず試すには充分かと思います。実運用される場合は、ディスクが満杯にならないよう要監視です。
まとめると、もし /app/myproject
が 10GB あるなら、/mnt
は少なくとも 30GB は確保したいところです。長期運用するなら大ざっぱに 100GB くらいでしょうか。
lsyncd を設定する
rsnapshot
のバックアップ先にデータを同期することになるので、まず転送先にディレクトリを作ります。
mkdir -p /mnt/rsnapshot/current/app/myproject/
設定ファイルはデフォルトで /etc/lsyncd.conf
です。ちなみに Lua 互換の形式です。
vi /etc/lsyncd.conf
ここでは root で実行することを前提としています。
settings {
logfile = "/var/log/lsyncd.log",
statusFile = "/tmp/lsyncd.status",
maxDelays = 1,
}
sync {
default.rsync,
source = "/app/myproject/",
target = "/mnt/rsnapshot/current/app/myproject/",
delete = true,
rsync = {
archive = true,
hard_links = true,
}
}
sync セクションは複数書くことできます。詳しいオプションはマニュアルをどうぞ。
削除の扱い
もし手元で削除したファイルも残しておきたいなら delete = false
を指定します。より安全ですが、たまたま間違えて手元にコピーした巨大なファイルが残り続けるかもしれません。基本的には true でよいでしょう。実運用する時は delete = running
を指定することを検討してみて下さい。
起動する
systemctl start lsyncd
手元で動作をみたい場合は settings セクションに nodaemon = true
を指定するか、あるいは次にように実行します。
lsyncd -nodaemon /etc/lsyncd.conf
rsnapshot を設定する
設定ファイルはデフォルトで /etc/rsnapshot.conf
です。brew で入れた方は /usr/local/etc/rsnapshot.conf
ですが、うまく読み込んでくれない場合は都度 -c /usr/local/etc/rsnapshot.conf
などと指定してください。
vi /etc/rsnapshot.conf
ここでは root で実行することを前提としています。個人のホームディレクトリ以下が対象なら一般ユーザでも動かせると思います、その場合はログファイルの場所などを調整してください。
config_version 1.2
snapshot_root /mnt/rsnapshot/
cmd_rsync /usr/bin/rsync
cmd_rsnapshot_diff /usr/bin/rsnapshot-diff
retain hourly 24
retain daily 7
retain weekly 4
retain monthly 12
retain yearly 10
logfile /var/log/rsnapshot.log
lockfile /var/run/rsnapshot.pid
rsync_short_args -a
rsync_long_args --delete-after --numeric-ids --relative --delete-excluded
link_dest 1
sync_first 1
backup /mnt/rsnapshot/current/app/myproject/ myproject
項目の区切りはスペースではなくタブのみ使えます。マニュアルも参照してみてください。
なお、backup
はいくつでも指定できます(lsyncd.conf
の sync セクションと合わせてください)。
世代を設計する
上記の設定だと、1時間毎に前回からの変更点のバックアップを取り、そのうち最古の1つを残し「その日」を代表するバックアップとすることで毎日のバックアップとし、そのうち最古の1つを残し「その週」を代表するバックアップとし…… という仕組みで、直近であるほどたくさんのバックアップを残し、最終的に1年に1つの代表データを保持することになります。
これを超えたデータは最終世代の実行時、つまり rsnapshot yearly
によって消去されます。
Time Machine に合わせる例
次のようになるでしょう。個人のデータ(とくにクリエイティブ系)が対象だとこちらのほうが実用的かもしれませんね。
retain hourly 24
retain daily 30
retain weekly 520 # 10年分
ただし、実際の Time Machine と違って、ディスク容量がいっぱいになる前に古いものが自動的に消えたりはしないので weekly の数は慎重に調整してください。
世代を新設する例
たとえば季節ごとに年4回保存する世代を間に挟むこともできるでしょう。なお、retain
を書く順序が大切ですのでこの場合は必ず monthly
と yearly
の間に入れて下さい。
retain seasonally 4
そして、3か月に1回 rsnapshot seasonally
を実行するよう cron に仕込みます(後述)。早い話、cron で実行する間隔にマッチしていればいいわけです。
データの同期をテストする
これで cron を仕込めば稼働はしますが、まずは手作業で動作を理解するのがよいでしょう。
テスト用のフラグ -t
を指定して、同期時に実際にどういったコマンドが実行されるのかチェックします。
rsnapshot -t sync
echo 75394 > /var/run/rsnapshot.pid
mkdir -m 0755 -p /mnt/rsnapshot/.sync/
rsync -a --delete-after --numeric-ids --relative \
--delete-excluded /mnt/rsnapshot/current/app/myproject/ \
/mnt/rsnapshot/.sync/myproject
touch /mnt/rsnapshot/.sync/
(注:コマンド形式で出力されますが、これとまったく同一のコマンドが発行されるわけではなく、実際には同等の動きをする Perl のコードが実行されます。つまり論理的な動きを表している、というわけです。以下同じ)。
問題なさそうなら、初回の同期を実行してみます。ついでにデバッグフラグ -v
を付けましょう。全データをコピーしますから、初回はかなり時間がかかるかもしれません。
rsnapshot -v sync
無事に完了すれば /mnt/rsnapshot/.sync
の中にデータがコピーされているはずです。
世代のローテートをテストする
最小単位(=設定ファイルにある複数の retain
行の一番上の世代)である hourly
を実行してみます。
rsnapshot -v hourly
echo 75977 > /var/run/rsnapshot.pid
mv /mnt/rsnapshot/.sync/ /mnt/rsnapshot/hourly.0/
rm -f /var/run/rsnapshot.pid
.sync
が mv され hourly.0
ディレクトリになりました。
次に、バックアップ元の /app/myproject/
の中を適当に変更してから、再度手動で実行してみます(なお rsnapshot sync
した結果に変更がなければディレクトリ作成はスキップされます)。
その前に忘れず sync
しましょう。
rsnapshot -v sync && rsnapshot -v hourly
出力からローテートのところだけ抜き出しました。
mv /mnt/rsnapshot/hourly.0/ /mnt/rsnapshot/hourly.1/
mv /mnt/rsnapshot/.sync/ /mnt/rsnapshot/hourly.0/
上記のステップがあと22回繰り返されて hourly.23
ディレクトリが作成されると次のような動きになります。
mv /mnt/rsnapshot/hourly.22/ /mnt/rsnapshot/hourly.23/
mv /mnt/rsnapshot/hourly.21/ /mnt/rsnapshot/hourly.22/
mv /mnt/rsnapshot/hourly.20/ /mnt/rsnapshot/hourly.21/
...
mv /mnt/rsnapshot/hourly.2/ /mnt/rsnapshot/hourly.3/
mv /mnt/rsnapshot/hourly.1/ /mnt/rsnapshot/hourly.2/
mv /mnt/rsnapshot/hourly.0/ /mnt/rsnapshot/hourly.1/
mv /mnt/rsnapshot/.sync/ /mnt/rsnapshot/hourly.0/
次の世代である daily
が動作できる状況になります。sync
は hourly
が一時間に一度実行すれば充分ですから、コマンドは単に次のようになります。
rsnapshot -v daily
mv /mnt/rsnapshot/hourly.23/ /mnt/rsnapshot/daily.0/
シンプルな仕組みであることがよくわかります。実行した時点でもっとも古いものが hourly
世代の代表として daily
世代へと「引き渡され」るわけですね。
rsnapshot のタスクを登録する
上記の動きをふまえ、次のような設定を cron に仕込みます。ログの出力先などは適宜変更してください。
vi /etc/cron.d/rsnapshot
10 * * * * root /usr/bin/rsnapshot sync && /usr/bin/rsnapshot hourly >> /mnt/rsnapshot/cron.log 2>&1
15 3 * * * root /usr/bin/rsnapshot daily >> /mnt/rsnapshot/cron.log 2>&1
20 3 * * 0 root /usr/bin/rsnapshot weekly >> /mnt/rsnapshot/cron.log 2>&1
25 3 1 * * root /usr/bin/rsnapshot monthly >> /mnt/rsnapshot/cron.log 2>&1
30 3 1 1 * root /usr/bin/rsnapshot yearly >> /mnt/rsnapshot/cron.log 2>&1
Time Machine と同じ世代設計にしたい場合は、もちろん monthly や yearly の行は必要ありません。
特に日々の作業領域をバックアップする場合は、daily
以下の世代は実行する時間や曜日を注意深く設計して下さい。もっともデータの変更がなさそうな落ち着いた時間や曜日のバックアップを次の世代に引き渡すことで、たとえば日中にデスクトップに誤って作成した(そして即時コピーされてしまった)一時的で巨大なファイル等を持ち回らなくて済む確率が上がるはずです。
ついでに whenever をお使いの方のための例も置いておきます。
別サーバへのバックアップについて検討する
今回の構成では、別マシン上への直接のバックアップ作成は仕組み上できません(が、のちほど検討します)。rsnapshot
は pull が前提のツールであるのに対しlsyncd
は push が前提のツールであるため、両者の設計思想が見事にバッティングするためです。
ローカルマシン(の環境)が物理・論理問わず吹っ飛んだ時のためにリアルタイムバックアップをしたい場合がほとんどでしょうから、どのように他のマシン(ここではバックアップマシンと呼びます)へデータを転送し冗長性を確保するかが大きな課題となります。
他のマシンへデータをなるべくリアルタイムに転送するためのいくつかアイデアを挙げておきます。
定期的に別サーバへ転送する(rsync 版)
単純にバックアップデータディレクトリ /mnt/rsnapshot
以下 をなるべく短い間隔で別途 rsync を走らせて他のサーバへ転送する方法です。若干消極的で冗長ですが、シンプルで安全確実です。
*/3 * * * * root /usr/bin/nice -10 /usr/bin/rsync -azq --del --hard-links /mnt/rsnapshot/ you@exmaple.com:/path/to/backup/dir/
キモは --hard-links
フラグの指定で、これを省くと20倍くらいの(ハードリンクではなく)実データが転送されてしまいます。反面、結果的に冗長性はすごく確保できるのでディスク障害によるデータロストにはめっぽう強くなるでしょうから、データの重要度によってはそういった運用もアリかもしれません。
同期元(ローカルマシン)上でローテートされる関係上、--del
スイッチを付けておかないと整合性が取れなくなるような気がします。いずれにしてもバックアップの総容量はローカル側で調整すべきでしょうから、付けておくほうがよいと思います(未検証)。
定期的に別サーバへ転送する(lsyncd 版)
もちろん、どうせならこの転送自体も lsyncd
に行わせ、ダウンタイムを短くすることも可能です。lsyncd.conf
に新しい sync
セクションを追加します。
sync {
default.rsyncssh,
source = "/mnt/rsnapshot/",
host = "you@exmaple.com",
targetdir = "/path/to/backup/dir/",
delete = true,
ssh = {
identityFile = "/home/you/.ssh/id_rsa",
},
rsync = {
binary = "/usr/bin/rsync",
archive = true,
hard_links = true,
}
}
root で実行する想定なので、identityFile
で一般ユーザの秘密鍵を指定しています。
ただ、個人的には安定性を考えると上記の rsync 版を採用するほうが良いようにも思います。というか、どうせならどちらも仕込んでおくのが賢い運用となりそうです。
なお、current ディレクトリを exclude
ディレクティブで省かないでください。ハードリンクの関係か、データが正しくコピーされないようです。
バックアップマシンからデータを取り出す
過去の(つまり hourly.1
以降の)ファイルを参照する場合は、ふつうにアクセスすればよいので問題ありません。すべての世代ディレクトリ以下は整合性が取れているはずです(厳密には、バックアップ用の rsync/lsyncd プロセスが起動から1時間以内に完了していることが前提)。
問題は、最新のファイルを取り出したい時です。データのバックアップ転送のプロセスが完了しない限り、バックアップマシン上の最新のデータは整合性が取れていない状態にある可能性が高いと推測できます。
バックアップマシン上から最新のデータ一式を整合性を保った状態でサルベージする時には、次のような手順を踏むべきでしょう。
ローカルマシンが生きている場合
- 転送のプロセスの起動設定をオフにする
- rsync なら cron を停止
- lsyncd なら設定ファイルの該当行をコメントアウトして再起動
- 転送のプロセスが動作していないことを確認する(あるいは kill で落とす)
- 転送のプロセスを手動で実行し、正常に完了することを確認する
- データを取り出す
- 転送のプロセスの起動設定をオンにする
hourly.0
から取り出します。
ローカルマシンが吹っ飛んだ場合
hourly.0
の整合性が取れている保障が得られなくなったわけですから、安全性からみると hourly.1
から取り出すことになるでしょう。
運用する
特定のファイルを対象から除外したい
例えば個々のファイルのサイズにより制限したい時は lsyncd.conf
の rsync セクションに --max-size
を指定します。ほかにも rsync コマンドが受け付けるものならその多くは指定できるようです。
rsync = {
...
_extra = {
...
"--max-size=102400000",
}
}
特定のディレクトリを対象から除外したい
lsyncd.conf
の exclude セクションに指定できます。
exclude = {
"secrets/",
"downloads/"
}
同期 cron タスクの多重起動を防止したい
データの同期に要する時間が最小ローテート間隔(上記の設定では1時間)を上回るとタスクが多重起動しやっかいな状況に陥るので、これを防止します。
いくつか方法があると思いますが、私は timeout(1) と、daemontools に含まれる setlock を組み合わせて使っています。
15 3 * * * root /usr/bin/timeout --preserve-status --kill-after=5m 3600 /usr/local/bin/setlock -nx /var/tmp/rsnapshot_daily.lock /usr/bin/rsnapshot daily >> /mnt/rsnapshot/cron.log 2>&1
実際には、毎時の同期に常に30分以上かかるような状況で運用するのはやめたほうが安全でしょう。
バックアップが正しく取れているかどうか監視したい
Nagios で監視する例を検討します。
lsyncd
実際にファイルが転送されているかどうかを日々チェックしたいわけですが、これがなかなかやっかいです。なにしろファイルが変更されない限りはなにも転送されない(のが正しい動作)わけですから、必ず定期的に更新されるファイルの最終更新時間をチェックするほかありません。
ホームディレクトリ以下をバックアップするなら、アイデアとして次のようなファイルが使えそうです。
- ~/.bash_history
- ~/Desktop/.DS_Store
これらの最終更新時刻をチェックすればひとまずよさそうです。が、信頼性は低いですね。
/path/to/check_file_age -w 43200 -c 86400 /mnt/rsnapshot/current/app/myproject/something
確実性を求めるのなら、面倒ですが5分に1回くらい適当なファイルを更新するタスクを cron に仕込んで、そのファイルを監視する手が考えられます。容量をケチるために 0 バイトのファイルにしましょう。
*/5 * * * * you /bin/touch /app/myproject/latest
/path/to/check_file_age -w 330 -c 600 /mnt/rsnapshot/current/app/myproject/latest
その他の手としては、/mnt/rsnapshot/current/app/myproject/
以下を find(1) を使って最近更新されたファイルがあるかどうか探す方法も考えられますが、あまりスマートではありませんね。
rsnapshot
方針としては、hourly.0
ディレクトリの作成時刻が約1時間以内であれば、rsnapshot
のローテートが動いていると期待できます。
/path/to/check_file_age -w 3660 -c 7200 /mnt/rsnapshot/hourly.0
ディスクの残り容量を勘案して古いバックアップファイルを自動的に消したい
この問題は真面目に取り組むとかなり大変な気がします、簡単な解決法はないでしょう。ディスク容量を日頃からチェックし、世代の数を調整したり大きなファイルを除外するなど、地道な調整を行う必要がありそうです。次項も参考にどうぞ。
ディスクの残り容量を気にせずにバックアップしたい
AWS EC2 のインスタンス上で運用する場合に限定されますが、ひとつのアイデアとして Amazon EFS (Elastic File System) の利用が考えられます。EFS は容量無制限の NFS ディスクをマウントできるサービスです。が、私はまだ使ったことはありません(2017/01 時点で北米のリージョンでのみ提供)。
最初のバックアップ先 /mnt/rsnapshot
を EFS でマウントしたパスに指定することにより耐障害性が上がることを期待できるとともに、事実上ディスク容量の残りを気にする必要が永久になくなるでしょう(その代わりに費用を気にする必要はありますが)。
lsyncd が拾いきれなかったときにリカバリしたい
lsyncd はウォッチできるファイルの最大数を超えたりファイル名が長すぎたりすると失敗したり、ちょっとナイーブです。うまく転送しきれなかった場合に備えて、別途リカバリ用の rsync タスクを定期的に走らせると少し安心度が高まるかもしれません。
*/10 * * * * root /usr/bin/rsync -a --del --hard-links /app/myproject/ /mnt/rsnapshot/current/app/myproject/
転送エラーを検知するには lsyncd のログを監視する方法が考えられます。もちろん、対処療法に過ぎませんから環境や設定を見直すべきでしょう。
1分ごとに全データを残したい
真に剛の者なら1分ごとにすべてのバックアップを残したいかもしれませんね。minutely
を新設し、これ1本で回します。これぞ最強の世代バックアップシステムと言えましょう。
retain minutely 5259600 # 10年分!
* * * * * root /usr/bin/rsnapshot sync && /usr/bin/rsnapshot minutely >> /mnt/rsnapshot/cron.log 2>&1
ただ、同一ディレクトリの中に最大で 500 万ディレクトリも作るとたいへんにアクセスが遅くなると思いますので、せめて1か月より古いものは hourly 以下に落としたほうがよいでしょう。
え、1分なんて無限にも等しいからせめて1秒ごとに残したい? あなたはもしや AI かなにかですか。健闘を祈ります!
その他メモ
よく知られた落とし穴ですが、rsync でディレクトリを指定する時は末尾のスラッシュの有無で意味が変わるので注意してください。慣れないうちは「必ずスラッシュをつける」に統一しておくとトラブルは少ないと思います。
新しい lsyncd は新しめの rsync を要求します。バックアップ先マシンの rsync バージョンに気をつけて下さい(サーバ用 OS のパッケージでは古い可能性があります)。
最初から他のサーバへ直接データを転送する(探求者向け)
そもそも lsyncd
が直接 /mnt/rsnapshot/.sync
ディレクトリ以下にデータを放り込めれば、とてもスマートです。中間データ置き場として current/
をわざわざ用意するのは容量の無駄ですからね。
なぜこれができないかというと、rsnapshot
が .sync
ディレクトリを毎回 mv (rename) するからです。そのため、世代の数だけ実ファイルがコピーされ(そして1時間ごとに .sync
へフルに再転送され)、ディスクの使用量(とネットワーク帯域)がすごいことになってしまいます。
逆に考えると、「最初の世代の最新へのコピー」だけ、うまくハードリンクをコピーするよう rsnapshot
を改造してやれば実現できることになります。やっつけパッチを作ってみましたので、チャレンジャーな方はお試し下さい。
rename の代わりに次のようなコマンドを実行するようになります。理論上1回しか実行されませんので(毎回が新規フルコピー)、--del
系オプションは意味が無いので付けません。
rsync -a --link-dest=../.sync/ /mnt/rsnapshot/.sync/ /mnt/rsnapshot/hourly.0/
lsyncd.conf
は次のようになります。rsync+ssh でネットワーク越しに転送し、リモートの /var/rsnapshot
以下に格納することにしましょう。
sync {
default.rsyncssh,
source = "/app/myproject/",
host = "you@example.com",
targetdir = "/var/rsnapshot/.sync/app/myproject/",
delete = true,
ssh = {
identityFile = "/home/you/.ssh/id_rsa",
},
rsync = {
binary = "/usr/bin/rsync",
archive = true,
hard_links = true,
}
}
lsyncd の実行前に、転送先のディレクトリを作成しておきます。
ssh you@example.com mkdir -p /var/rsnapshot/.sync/app/myproject
rsnapshot.conf
の変更点は次の通りです。ローテート機能しか使わなくなるので、バックアップ元は適当にダミーを設定しておきます(ただし、存在しないパスだと rsnapshot が動作しません)。
...
backup /dev/null .
また、crontab に書いている rsnapshot sync
は要らなくなりますので削除します。
10 * * * * root /usr/bin/rsnapshot hourly >> /var/rsnapshot/cron.log 2>&1
15 3 * * * root /usr/bin/rsnapshot daily >> /var/rsnapshot/cron.log 2>&1
20 3 * * 0 root /usr/bin/rsnapshot weekly >> /var/rsnapshot/cron.log 2>&1
...
嬉しい副作用として、初期容量を元データの等倍しか必要としないシステムにアップグレードできました。ついでに ln -s .sync current
しておくと多少利便性が上がるでしょう。
おわり
数秒前に更新したデータから数年前のデータまでがひとつのディレクトリ以下に格納され、通常の操作ですぐに参照できる環境というのはなかなか万能感がありますよね。
実際に運用するとなるとまだ検討と経験が必要そうではありますが、今回の構成はひとまずのスタート地点になり得るのではと思います。
それでは、よいバックアップライフを!