« 2006年10月 | メイン | 2006年12月 »

2006年11月13日

dd_rescueでバックアップ

社内の共有サーバのディスクが壊れて、一部読み書きできないセクタがあるようなので、注文した交換用のディスクが届くのを待つ間に、Linuxのdd_rescueを使ってバックアップをとることにしました。
dd_rescueはディスクイメージをそのままコピーするddとほぼ同じ機能を持つコマンドで、とくにエラーが出る可能性があるディスクからデータを取り出すために、
・エラーセクタがあっても、コピーを続行できる(これは、ddのconv=noerrorオプションに相当する機能です)
・ファイルの後ろから順にコピーすることができる
・現在の進捗やエラーの発生回数の詳細な表示ができる
などの機能が強化されているものです。

たとえば、/dev/sdaの10Gバイト目から1Gバイト分のバックアップをとりたい場合は、次のようにします。

dd_rescue -A -m 1073741824 -s 10737418240 -S 0 /dev/sda backup_010.img

-A オプションは、エラーセクタ部分はゼロで埋める(ddのconv=syncに相当)
-m オプションはコピーするサイズ
-s オプションはコピー元の開始位置
-S オプションはコピー先の開始位置

です。-Sは省略すると-sと同じ値になります。したがって、上の例のように、ファイルにバックアップする際には -S 0 が必要になることが多いと思います。

サイズや開始位置には、b(=512 ブロックサイズ)、k(=1024)、M(=1048576)、G(=1073741824)の単位をつけることができますので、以下のように書いても同じ動作をします。

dd_rescue -A -m 1G -s 10G -S 0 /dev/sda backup_010.img

また、逆向きコピーの場合は、-r オプションを使って、以下のように書きます。

dd_rescue -r -A -m 1G -s 11G -S 1G /dev/sda backup_010.img

注意しないといけないのは、-s, -Sの値も変わることです。

以下の2つのコマンドを実行した結果は同じものになります。

dd_rescue -A -m $size -s $spos -S $dpos $sfile $dfile
dd_rescue -A -r -m $size -s $spos2 -S $dpos2 $sfile $dfile

ただし、 $spos2 = $spos + $size
かつ、 $dpos2 = $dpos + $size

あと、今回使ってみて便利だなと思ったのは、
・入出力をリダイレクトできる
ことです。ファイル名のところに、- を指定することができます。ddだとこれができません。

今回は、バックアップ先がwindows(smbmountしているディスク)で、空き容量もバックアップ元をすべてそのままおけるほど十分には残っていなかったので、
・元のイメージは1Gバイトごとに分割(2GまでOKだと思いますが、後で数えやすそうなので1Gにしました)
・それぞれの分割ファイルはgzipで圧縮
することにしました。

バックアップスクリプトは大体こんな感じです。
for i in `seq 0 160`
do
  f=`printf backup_sda_%03d $i`
  echo $f
  dd_rescue -A -m 1G -s ${i}G -S 0 /dev/sda - | gzip -c > $f.gz
done
リストア用はこれ。
for i in `seq 0 160`
do
  f=`printf backup_sda_%03d $i`
  echo $f
  zcat $f.gz | dd_rescue -S ${i}G - /dev/sda
done
たまに、dd_rescueがハングしてしまった時があったので、その部分は、-r オプションなども使って手作業でバックアップファイルをつくりました。