2016年3月30日水曜日

システムバックアップその9

ようやく、バックアップ処理のメインである「ファイル・ディレクトリ一式のバックアップ」処理だ。
ここまで永かった…。
 
お約束通り、まずはスクリプトだ。
sudo su - して root 権限を取得しておくのを忘れないようにね。
# cd
# cd backup/bin
# vi 0050_create_archive

中身はこんな風に
--中身ココから--
#!/bin/sh

BINDIR=`/usr/bin/dirname $0`
BINDIR=`/usr/bin/realpath ${BINDIR}`
ETCDIR=`/usr/bin/realpath ${BINDIR}/../etc`

. ${ETCDIR}/config

# Backup Start
for FSCONFIG in ${ETCDIR}/fsconfig/*
do
  VOLNAME=""
  USELVM=""
  MOUNTPOINT=""

  . ${FSCONFIG}

  . ${BACKUPPOINT}/current/config/blkid/${VOLNAME}

  if [ x${USELVM} = "xNo" ]
  then
    /bin/mount --bind ${MOUNTPOINT} \
                      ${BACKUPPOINT}/current/snapshot
    /bin/tar -cj \
             -f ${BACKUPPOINT}/current/archive/${VOLNAME}.tbz \
             -C ${BACKUPPOINT}/current/snapshot \
                .
    /bin/umount ${BACKUPPOINT}/current/snapshot
  fi

  if [ x${USELVM} = "xYes" -a x${TYPE} != "xswap" ]
  then
    /bin/mount -o ro /dev/${ROOTVG}/${VOLNAME}.snap \
                     ${BACKUPPOINT}/current/snapshot
    /bin/tar -cj \
             -f ${BACKUPPOINT}/current/archive/${VOLNAME}.tbz \
             -C ${BACKUPPOINT}/current/snapshot \
                .
    /bin/umount ${BACKUPPOINT}/current/snapshot
  fi

done

--中身ココまで--
これまでのスクリプトを読んでいれば、こちらはそんなに複雑ではないはずだ。
最初に基本変数を読み込んで、fsconfigの下にある設定ファイル分だけループを回す。
そのループの中で、
  • LVMを使用していない場合
    対象の領域を、current/snapshot へ bindオプション付きでマウント。
    tar で、当該領域を吸い上げ、current/archive ディレクトリへ書き込み。
    終わったらアンマウント。
  • LVMを使用している&当該領域がswapではない場合
    対象領域の snapshot 領域を、current/snapshot へリードオンリーでマウント。
    tar で、当該領域を吸い上げ、current/archive ディレクトリへ書き込み。
    ​終わったらアンマウント。
という処理を行っているだけだ。
ここで初出の変数は(多分)一つだけ。
${MOUNTPOINT}
だ。
 
これは、mount --bind と合わせて使用している。
既にマウント済みの領域は、他のマウントポイントにはマウント出来ない。
LVM領域の場合は、snapshot を作成した上で、その snapshot からファイルを吸い上げるので、特に関係は無い。
問題なのはLVM以外の領域(具体的には、sda1 / sda2 の2領域)だ。
こちらは、既にマウントされている状態のため、current/snapshot へマウントすることが出来ない。
そこで出てくるのが --bind オプションだ。
このオプションは、ある特定のディレクトリ、ファイルを別の場所に再マウントしたように見せかけるオプションだ。
(ファイルの場合、ハードリンクでもいいと思う人もいるかもしれないけど、ハードリンクは同一のファイルシステム内でしか利用出来ない。)
これによって、/boot や /boot/efi 等のディレクトリ以下を、current/sunapshot へ再マウントしているかのように見せかけている。
しかも、デフォルトでは下位マウントポイントまではマウントされない。
つまり、 mount -o bind /boot ..../current/snapshot とマウントしても、/boot/efi の下のファイルは .../current/snapshot/efi の下には現れないんだ。
これによって、/boot ファイルシステムのみを、.../current/snapshot に見せることが出来る。
バックアップの形式には tar を用いている。
Unix系OS界隈では、「バックアップに tar を用いてはいけない」という都市伝説がある。
実際、「tar ではなく cpio を用いるように」とか、dumpコマンドでバックアップを取るやり方を紹介しているところが多い。
確かに tar は、アーカイブファイル(バックアップファイル)の途中が破損した場合、その破損部以降は全て読み取ることが出来ない。
それに対して cpio は、その破損部より後ろでも、正常な部分は読み取ることが可能だ。
そういう理由で、tar ではなく cpio を薦めている人が多い。
 
だけどちょっと考えてみて欲しい。
今回取得しようとしているのは、OSのバックアップだ。
OS領域をリストアした結果、アーカイブファイル(バックアップファイル)の一部が破損していたので、破損部以外をリストアしました、というのは、そのシステムを安心して使えるだろうか?
一部が壊れているのであれば、それはアーカイブファイル全体が壊れていると考えた方が安全ではないだろうか?
ということで、cpio の優位性の一つはあまり優位ではないと考えている。
ついでに tar を使用している理由としては、以前 Linus Tovalds が「バックアップは tar を使え」と言っていた記事を見たからだ。(その記事がドコにあるか、もはや覚えていないが…)
 
ちなみに、ファイルシステムに xfs を使用している場合は、別の手順になると思われる。
一応、想定で書くと、以下のブロックを追記しておく必要があるのではなかろうか?
--ココから--
  if [ x${USELVM} = "xYes" -a x${TYPE} = "xfs" ]
  then
    /bin/mount -o ro,no-uuid /dev/${ROOTVG}/${VOLNAME}.snap \
                     ${BACKUPPOINT}/current/snapshot
    xfsdump -l 0 \
             -f ${BACKUPPOINT}/current/archive/${VOLNAME}.tbz \
             ${BACKUPPOINT}/current/snapshot \
    /bin/umount ${BACKUPPOINT}/current/snapshot
  fi

--ココまで--
合わせて、ext4をバックアップしているところも、以下のように書き換えておく必要が有ると思われる。
--ココから--
  if [ x${USELVM} = "xYes" -a x${TYPE} != "xswap" ]
  ~
  fi


  if [ x${USELVM} = "xYes" ]
    if [    x${TYPE} = "xext2"
         -o x${TYPE} = "xext3" 
         -o x${TYPE} = "xext4" ]
    ~
    fi
  fi

--ココまで--
動作検証一切していないので、動く自信は一切ない。注意。
 
さて、変数の話に戻って、${MOUNTPOINT}だ。
これは、ファイルシステム毎に定義するべき内容なので、定義先は etc/fsconfig/* になる。
今は3つ定義ファイルがあると思うので、それぞれ以下の内容を追記してしまおう。
# vi ../etc/fsconfig/0010_sda1
--追記ココから--
#
# MOUNTPOINT:
# Specify the mount point of the target area.
#
MOUNTPOINT=/boot/efi

--追記ココまで--
 
# vi ../etc/fsconfig/0020_sda2
--追記ココから--
#
# MOUNTPOINT:
# Specify the mount point of the target area.
#
MOUNTPOINT=/boot

--追記ココまで--
 
# vi ../etc/fsconfig/0030_lv-root
--追記ココから--
#
# MOUNTPOINT:
# Specify the mount point of the target area.
#
MOUNTPOINT=/

--追記ココまで--
 
変数定義も出来たので、動作確認してみよう。
例によって、実行パーミッションを付与しておくところから。
# chmod +x 0050_create_archive
# ./0010_mount
# ./0020_mkdir
# ./0030_create_config
# ./0040_create_snapshot
# ./0050_create_archive

(0050_create_archive は少し時間がかかる。何も画面変化が無いけど、慌てないように。数分~20分も待てば、プロンプトが返ってくるはずだ。)
(人によっては、「/bin/tar: ./ssh-XXXX/agent.NNNN: ソケットは無視します」のようなメッセージが出ているかもしれない。これはソケットファイルというもので、sshでログインしていて、agent転送を許可している場合に自動的に作られるソケットファイルだが、バックアップする必要が無いものなので、気にしなくてイイ。)
無事に処理が完了したら、アーカイブファイルが出来上がっているはずだ。
ファイルは、current/archive の下にあるはず。見てみよう。
# ls -l /media/backup/current/archive
多分、sda1.tbz、sda2.tbz、lv-root.tbz という3つのファイルが出来ているのではないだろうか?
それぞれ、ちゃんとファイルが格納されているか、ファイル一覧も見てみよう。
# tar tvjf /media/backup/current/archive/sda1.tbz
# tar tvjf /media/backup/current/archive/sda2.tbz
# tar tvjf /media/backup/current/archive/lv-root.tbz

ファイルのバックアップは無事に完了だ。
必要な領域分、定義ファイルを作成しないといけないが。
 
さて、動作確認が取れた所で、(今のバックアップは中途半端なゴミなので)削除して戻しておこう。
# rm -rf /media/backup/current
# umount /media/backup
# lvremove /dev/vg-root/lv-root.snap

 
今回はココまで。
次回は snapshot の削除だ。

0 件のコメント:

コメントを投稿