バックアップは cron + rsync にお任せ! #ieAdventCalendar2017

Share on:

自由気ままにアドベントカレンダーその2(続いた)。卒業生含めて書きたい人は書くと良いよ! 今回のキーワードは「バックアップは cron + rsyncさんにお任せ!」と書いてますが、本題はrsyncです。cronはググってみよう(酷い)。

MacはOS Xになってからだったか、Time Machine付くことでかなりユーザフレンドリーなバックアップ環境が整いましたね。一方、Linux系OSではどうしたら良いでしょう。VMならそのイメージファイル全体を定期的に複製するみたいなやり方もあるかもしれませんが、ここではファイル単位でのバックアップを考えてみます。


1. cpの限界

ファイルのバックアップを取る場合、真っ先に思いつくのはcp, scpによるファイル複製でしょうか。試しにやってみましょう。

今、以下のようなディレクトリ構成になっているとします。
バックアップ対象を「home」としています。この下にroot, tnalがあり、各々hoge.txtというファイルだけがあります。ls -lから分かるように、rootディレクトリ以下は root:wheel というowner:group にしてあります。

oct:tnal% find .
.
./home
./home/root
./home/root/hoge.txt
./home/tnal
./home/tnal/hoge.txt
./mnt
./mnt/other-media
oct:tnal% ls -l home/
total 0
drwxr-xr-x  3 root  wheel  102 12 23 09:33 root/
drwxr-xr-x  3 tnal  staff  102 12 23 09:33 tnal/

home全体を、「mnt/other-media」以下に cp で複製してみましょう。

# case 1-1: cp -r で指定したディレクトリ以下を再帰的にコピーしてみる。
oct:tnal% cp -r home/ mnt/other-media/home/
oct:tnal% ls -l mnt/other-media/home/
total 0
drwxr-xr-x  3 tnal  staff  102 12 23 09:43 root/
drwxr-xr-x  3 tnal  staff  102 12 23 09:43 tnal/

case 1-2: もう一度同じコマンドを実行してみる。

oct:tnal% cp -r home/ mnt/other-media/home/ overwrite mnt/other-media/home/root/hoge.txt? (y/n [n]) not overwritten overwrite mnt/other-media/home/tnal/hoge.txt? (y/n [n]) not overwritten

case1-1では、-r オプションを付けることでディレクトリ全体を複製しています。一方で、このコマンドを実行したユーザは tnal のため、rootディレクトリのowerやgroupが変わってしまいました。また、タイムスタンプも違います。owner等が変わってしまうのは当然困りますね。また、mnt以下の方が新しい日付になってしまっていますが、これも嬉しくありません。例えば、バックアップ先からファイル復元しようしても「どれが更新済みか」をタイムスタンプでは判断できないため、ファイル復元しようとする都度、全体を上書きする必要があります。個人PCぐらいならそれでも良いかもしれませんが、1研究室なり複数人で利用している環境だとこのコストは馬鹿になりません。

case1-2では、1週間後とか適当な期間が過ぎ、改めてバックアップを取りたいという状況で同じコマンドを実行した状態を想定して、同じコマンドを実行した様子を示しています。今回の例では、home 以下は全く変更していない状態のため改めてバックアップする必要はないという状況です。しかし、同じコマンドを実行すると複製先に既にファイルが存在しているために、ユーザ自身に上書きするかどうかの判断を委ねられています。全てyes回答させるオプションもありますが、更新していないにも関わらず上書きするのは無駄が大きすぎます。

ということで、もうひと工夫してみた例が以下です。ここではsudoを使い、cpコマンドに-aオプションを付けてみました。

# case 2-1: sudo 付きで cp -a オプション実行してみる。
oct:tnal% sudo cp -a home/ mnt/other-media/home/
oct:tnal% ls -l mnt/other-media/home/
total 0
drwxr-xr-x  3 root  wheel  102 12 23 09:33 root/
drwxr-xr-x  3 tnal  staff  102 12 23 10:01 tnal/

case 2-2: もう一度同じコマンドを実行してみる。

oct:tnal% sudo cp -a home/ mnt/other-media/home/ oct:tnal% ls -l mnt/other-media/home/ total 0 drwxr-xr-x 3 root wheel 102 12 23 09:33 root/ drwxr-xr-x 3 tnal staff 102 12 23 10:01 tnal/

case2-1では、rootディレクトリのonwer:group情報も保持しており、またタイムタンプも同じ状態で複製されていることが確認できます。(tnalディレクトリのタイムスタンプが更新されていますが、これは別用途で作業したため。)

case2-2では、同じコマンドを再度実行したとしても何も聞かれず複製が実行され、同じ状態が保たれていることが確認できます。

ということでこれで晴れて万々歳と言いたいところですが、cpコマンドは「コピーするためのコマンド」です。このため、ファイル更新の有無に関わらず、実行する都度すべての対象をコピーします。例えば数GB〜数TBあるような動画ファイルを保存していたとして、全く変更していないのだとしても、毎回必ずコピーします。また、初回のバックアップ時に100万ファイル複製したとして、次回バックアップ時点では10個だけファイル更新があったとしても、また100万ファイル全体の複製からやります。とっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっても無駄ですね。そこで、rsyncさんの出番です。


2. rsyncで同期してみる

oct:tnal% apropos rsync
colorsyncd(8)            - ColorSync Daemon
newwin(3x), delwin(3x), mvwin(3x), subwin(3x), derwin(3x), mvderwin(3x), dupwin(3x), wsyncup(3x), syncok(3x), wcursyncup(3x), wsyncdown(3x) - create curses windows
rsync(1)                 - faster, flexible replacement for rcp
rsyncd.conf(5)           - configuration file for rsync in daemon mode

上記はrsyncコマンドについてaproposコマンドで調べてみた際の結果です。「faster, flexible replacement for rcp」とあるように、rcpコマンドを置き換える、高速で柔軟性のあるコマンドがrsyncです。もちろんパーミッションを保持できますし、「変更されていない対象は複製しません」。rsyncの「sync」はシンクロ、つまり同期の意味で、バックアップ対象とバックアップ先が同期されるように作業します。同期が取れているか否かをチェックサムアルゴリズムで判定していますが、この辺りを掘り下げるのは本題ではないため、wikipediaに丸投げしておきます。ここでは「変更されていない対象は複製しません」ことだけを覚えてれば十分です。

では、一度 mnt/other-mediia/homeをまっさらにした上で rsync コマンドを実行してみましょう。

# バックアップ先をクリア。
oct:tnal% sudo rm -rf mnt/other-media/home
oct:tnal% ls mnt/other-media/

case 3-1: sudo付きでrsyncコマンドを実行。

oct:tnal% sudo rsync -auvz home/ mnt/other-media/home/ building file list ... done created directory mnt/other-media/home ./ root/ root/hoge.txt tnal/ tnal/hoge.txt

sent 277 bytes received 82 bytes 718.00 bytes/sec total size is 0 speedup is 0.00 oct:tnal% ls -l mnt/other-media/home/ total 0 drwxr-xr-x 3 root wheel 102 12 23 09:33 root/ drwxr-xr-x 3 tnal staff 102 12 23 10:01 tnal/

case 3-2: もう一度同じコマンドを実行してみる。

oct:tnal% sudo rsync -auvz home/ mnt/other-media/home/ building file list ... done

sent 181 bytes received 20 bytes 402.00 bytes/sec total size is 0 speedup is 0.00 oct:tnal%

case3-1は、rsyncに-auvzオプション付きで複製した例です。ちゃんと複製できてることが確認できますね。-aはアーカイブモード、-uは複製先のファイルが新しい場合にはスキップ、-vは動作状況の出力、-zは同じメディア内なら多分邪魔ですが、ファイル転送する際に圧縮してくれるオプションです。他にもよく使うオプションは「–delete(バックアップ対象で削除されたファイルがあれば、バックアップ先でも削除する)」かな。

そしてcase3-2は、先程と同様に同じコマンドを実行した際の様子です。先ほどとは出力内容が異なり、既にバックアップ対象とバックアップ先の同期が取れている(更新がない)ため、全ての複製をスキップしています。rsync偉い!


まとめのようなもの

以上、cp使うなという話ではなく、状況に応じて使い分けようということで違いを観察できるような例を紹介してみました。また、今回は同じファイルシステム上にバックアップを取る形でやりましたが、rsyncはネットワークを介して別システムに複製を取ることもできます。例えば「rsync -auvze ssh home/ tnal@hostA.jp:/mnt/home/」とやると、hostA.jpというマシンにtnalアカウントでssh接続して、同期を実行します。同期するコマンドなので、2回目以降は更新があるファイルだけが転送されるため、とても効率が良いです。

また、rsyncコマンドをシェルスクリプトとして用意し、cron実行することで「自動的に定期的に指定したバックアップを実行」してくれるようになります。実際、それで助かったことがあります(遠い目)。重要度に応じて2重ではなく3重バックアップ取ることで「こんなこともあろうかと」と言える人生を目指しましょう!