2007-07-15

λ [FreeBSD] dump & restore 戦略

参考: dumpコマンドとrestoreコマンドの使い方

最近のFreeBSDの dump コマンドには -L オプションがある。snapshot を利用して運用中でも安全にダンプを取ることが出来る。

ダンプの仕方については解説が簡単に見つかるのだが、複数のlevelを利用した場合の説明がなかなか見つからない。 バックアップファイルだけ取って安心しているのかもしれないし、リストアするような状態の時にはそれどころではないのかもしれないし。

ハノイの塔シーケンスというのが man dump にも載っているんだけど、これの最大の問題は直感的ではないところ。 特に軽くパニック状態のリストア状態になった時に「どのダンプファイルをどの順番で適用すればいいのか」がすぐに分らない。 折角途中までリストアしたのに失敗してしまったら(そういう状況では大概スピードを求められているはずなので)最悪だ。

0 -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8 ->
1(a) -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8 ->
1(b) -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8 -> 0 に戻る

なので毎月同じ日には同じlevelのバックアップファイルを取ることにする。

dump する時のダンプレベル早見表
 1日 : 0 (毎回新tape。年月を記録する)
 2日 : 3
 3日 : 2
 4日 : 5
 5日 : 4
 6日 : 7
 7日 : 6
 8日 : 9
 9日 : 8
10日 : 1 (tape A)
11日 : 3
12日 : 2
13日 : 5
14日 : 4
15日 : 7
16日 : 6
17日 : 9
18日 : 8
19日 : 1 (tape B)
20日 : 3
21日 : 2
22日 : 5
23日 : 4
24日 : 7
25日 : 6
26日 : 9
27日 : 8
28日 : 1 (tape C)
29日 : 3
30日 : 2
31日 : 5

で、何かあって「その日の状態まで戻す」には、どの日のバックアップを使うべきかが次の表

restore する時の対象ダンプファイル早見表(カッコ内はダンプレベル)
 1日 : 1日 (0)
 2日 : 1日+2日 (0,3)
 3日 : 1日+3日 (0,2)
 4日 : 1日+3日+4日 (0,2,5)
 5日 : 1日+3日+5日 (0,2,4)
 6日 : 1日+3日+5日+6日 (0,2,4,7)
 7日 : 1日+3日+5日+7日 (0,2,4,6)
 8日 : 1日+3日+5日+7日+8日 (0,2,4,6,9)
 9日 : 1日+3日+5日+7日+9日 (0,2,4,6,8)
10日 : 1日+10日 (0,1)
11日 : 1日+10日+11日 (0,1,3)
12日 : 1日+10日+12日 (0,1,2)
13日 : 1日+10日+12日+13日 (0,1,2,5)
14日 : 1日+10日+12日+14日 (0,1,2,4)
15日 : 1日+10日+12日+14日+15日 (0,1,2,4,7)
16日 : 1日+10日+12日+14日+16日 (0,1,2,4,6)
17日 : 1日+10日+12日+14日+16日+17日 (0,1,2,4,6,9)
18日 : 1日+10日+12日+14日+16日+18日 (0,1,2,4,6,8)
19日 : 1日+19日 (0,1)
20日 : 1日+19日+20日 (0,1,3)
21日 : 1日+19日+21日 (0,1,2)
22日 : 1日+19日+21日+22日 (0,1,2,5)
23日 : 1日+19日+21日+23日 (0,1,2,4)
24日 : 1日+19日+21日+23日+24日 (0,1,2,4,7)
25日 : 1日+19日+21日+23日+25日 (0,1,2,4,6)
26日 : 1日+19日+21日+23日+25日+26日 (0,1,2,4,6,9)
27日 : 1日+19日+21日+23日+25日+27日 (0,1,2,4,6,8)
28日 : 1日+28日 (0,1)
29日 : 1日+28日+29日 (0,1,3)
30日 : 1日+28日+30日 (0,1,2)
31日 : 1日+28日+30日+31日 (0,1,5)

dumpHanoiByDate コマンド(第一引数にファイルシステムを指定する):

#!/bin/sh
setdumplevel () {
  local d -
  d=`date +%e | tr -d ' '`
  set 0 3 2 5 4 7 6 9 8 1 3 2 5 4 7 6 9 8 1 3 2 5 4 7 6 9 8 1 3 2 5 4 7 6 9 8
  eval "dumplevel=\${$d}"
}
setdumplevel
/sbin/dump -$dumplevel -uaL -h0 -f - $1 | nice bzip2

これをバックアップしたい方のマシンに仕込んで置いて、ssh でダンプを抽出する予定。 (8/1追記) 日付を取得するところを date +%d にしていると、1日の場合 '01' が返って来て $01 を評価しようとして失敗してしまった。date +%e で ' 1'(1文字目スペース) を返すようにしてスペース除去、というように変更した。

(追記) バックアップファイルをハードディスクに1年分保存しときゃいいか、な受け側のスクリプト。(バックアップファイルのファイル名が 月日 ベースなので。年に1回さらに別メディアにコピーしとけば更に長期間の保存ができることになる。)

#!/bin/sh
d=`date +%m%d`
ssh -i ~/.ssh/id_rsa_dumpHanoiByDateroot -l root tobebackuped.example.com /root/dumpHanoiByDate / > /BigDrive/tobebackuped.example.com/root.${d}.bz2
ssh -i ~/.ssh/id_rsa_dumpHanoiByDatevar -l root tobebackuped.example.com /root/dumpHanoiByDate /var > /BigDrive/tobebackuped.example.com/var.${d}.bz2
ssh -i ~/.ssh/id_rsa_dumpHanoiByDateusr -l root tobebackuped.example.com /root/dumpHanoiByDate /usr > /BigDrive/tobebackuped.example.com/usr.${d}.bz2
ssh -i ~/.ssh/id_rsa_dumpHanoiByDatehome -l root tobebackuped.example.com /root/dumpHanoiByDate /home > /BigDrive/tobebackuped.example.com/home.${d}.bz2

バックアップする側(tobebackuped.example.com)の /root/.ssh/autholized_keys には以下のように書いておく。実行されるコマンドは、この /root/.ssh/autholized_keys と鍵の組み合わせで決まっており、受け側のスクリプトに書いてあるコマンドは無視される。(man sshd 参照)

command="/root/dumpHanoiByDate /",no-pty,no-port-forwarding ssh-rsa AAAA...
command="/root/dumpHanoiByDate /var",no-pty,no-port-forwarding ssh-rsa AAAA...
command="/root/dumpHanoiByDate /usr",no-pty,no-port-forwarding ssh-rsa AAAA...
command="/root/dumpHanoiByDate /home",no-pty,no-port-forwarding ssh-rsa AAAA...

(2008/1/3 追記) dump でファイルを除外する を有効にするために、dump 時に -h0 オプションを追加。 /usr/obj 等に chflags nodump をかけて容量を節約する。

λ [FreeBSD] nullfs でマウントしている時の dump

以下のような /etc/fstab で、nullfs によるマウントをしていると、 dump -0uaL -f - /usr コマンド等の実行で dump コマンドが対象とするファイルシステムをどうすればよいか混乱してdumpできない。

このような場合デバイス名を利用して dump -0uaL -f - /dev/ufs/usr とすればよい。

# Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/label/swap1        none            swap    sw              0       0
/dev/ad0s1a             /               ufs     rw              1       1
/dev/ufs/home           /home           ufs     rw              2       2
/dev/ufs/usr            /usr            ufs     rw              2       2
/dev/ufs/var            /var            ufs     rw              2       2
/dev/acd0               /cdrom          cd9660  ro,noauto       0       0
# for jail
/usr    /var/jail/mimori.org/usr        nullfs  ro              0       0
/home   /var/jail/mimori.org/home       nullfs  rw              0       0
[]