(SSDが潤沢にあればこんなことしなくて良いのに!)
また、ホストマシン側は 4GBのSSDしか使用できない環境なので、今回はゲストマシン側だけで何とかします。
(SSDが潤沢にあればこんなことしなくて良いのに!!)
なお、このblogは例によってメモ for 未来の私 です。
ゲストマシン環境
ディスクマウント状態はこんな感じ
/dev/xvda3 /dataは SDHCです。
バックアップ対象は /(/dev/xvda1) だけです。
バックアップ保存先は /data(/dev/xvda3) です。
/dev/xvda1 none swap sw 0 0
/dev/xvda2 / ext3 rw,noatime,nodiratime,errors=remount-ro 0 0
/dev/xvda3 /data ext3 rw,noatime,nodiratime 0 0
ホストマシン側から見ると、
/dev/xvda1 と /dev/xvda2 は EeePC 4G-X 上のSSDに保存されている ディスクイメージファイル(スパースファイル)です。
/dev/xvda3 は外付けSDHC(/dev/sdc1)です。
ホストマシン側でマウントしているデバイスはゲストマシンでマウントできないため、ホストマシンは /dev/sdc1はマウントしていません。
仮想マシン起動用のcfgはこんな感じ(抜粋)
disk = [
'file:/data_local/xen/domains/alpha/disk.img,xvda2,w',
'phy:/dev/sdc1,xvda3,w',
'file:/data_local/xen/domains/alpha/swap.img,xvda1,w',
]
バックアップ手順
1. ディスクイメージ作成
2GBのスパースファイルを作成します。
作成先は /data/tmp/disk.img です。
# dd if=/dev/zero of=/data/tmp/disk.img bs=1024M seek=2 count=0
2. ファイルシステム作成
作成したディスクイメージに ext3ファイルシステムを構築します。
対話的に y/n を聞かれることがあるので、自動的に y を答えるようにします。
# echo "y" | /sbin/mkfs -t ext3 /data/tmp/disk.img
3. 作成した空ディスクをマウント
ループバックデバイスとして作成したディスクを /mnt/tmp にマウントします。
# mount -o loop /data/tmp/disk.img /mnt/tmp
4. コピー
rsyncを使用して、/(ファイルすべて) を /mnt/tmp にコピーします。
ただし、SDHCである /data/ と マウントしている /mnt/tmp/ は除外します。
90秒スリープしているのはバッファの内容を書きこむのを待っているため。sleepしなくても良いのですが、なんとなく。
# /usr/bin/rsync -Sax / /mnt/tmp --exclude "/data/" --exclude "/mnt/tmp/"
# sleep 900
5. アンマウント
マウントを解除します。
# umount /mnt/tmp
6. GNU tarでアーカイブ
gzip や bzip2 では sparseとしての扱いが出来ずに、今回であれば 2GBのファイルとして扱ってしまいますが、sparseファイルが扱える GNU tar (Sオプション)を使い、/data/tmp/disk.img から /data/Dropbox/backup/disk.img.tgz を作成します。
# cd /data/tmp
# tar -Szcf /data/Dropbox/backup/disk.img.tgz ./disk.img
/data/Dropbox は Dropbox同期ディレクトリになっているので、ここに保存した disk.img.tgz はDropboxクラウドやLAN同期を経由して手元のMacにも転送されます。
これでバックアップは終了です。
これらバックアップはスクリプトにして、cronで週3回ほど自動実行させています。
スクリプトはこんな感じ。バックアップ開始/終了をtwitterにpostしています。
USERNAME@SERVER:# cat backup_image.sh
#! /bin/sh
set -x
TMP_DIR=/data/tmp
TMP_IMAGE=disk.img
DST_DIR=/data/Dropbox/backup
DST_FILE=disk.img.tgz
MNT_POINT=/mnt/tmp
TMP_FILE=/tmp/tmp.$$
TW_POST=/home/root/bin/twitter_post.pl
# mount check
# if mounted /mnt/tmp , this script will finish.
df | grep '/mnt/tmp$' > /dev/null
test $? -eq 0 && exit
#
if [ -f $TW_POST ]; then
HM=`date +%H:%M`
echo "disk image backup start at $HM" > $TMP_FILE
$TW_POST $TMP_FILE
rm $TMP_FILE
fi
test -f $TMP_DIR/$TMP_IMAGE && rm -f $TMP_DIR/$TMP_IMAGE
# make new 2GB sparse file
dd if=/dev/zero of=$TMP_DIR/$TMP_IMAGE bs=1024M seek=2 count=0
echo "y" | /sbin/mkfs -t ext3 $TMP_DIR/$TMP_IMAGE
# mount image
test ! -d $MNT_POINT && mkdir -p $MNT_POINT
mount -o loop $TMP_DIR/$TMP_IMAGE $MNT_POINT
# mount check
# if NOT mounted /mnt/tmp , this script will finish.
df | grep '/mnt/tmp$' > /dev/null
if [ $? -ne 0 ]; then
if [ -f $TW_POST ]; then
HM=`date +%H:%M`
echo "disk cannot mounted. abort. $HM" > $TMP_FILE
$TW_POST $TMP_FILE
rm $TMP_FILE
fi
exit
fi
# copy
/usr/bin/rsync -Sax / $MNT_POINT --exclude "/data/" --exclude "$MNT_POINT/"
sleep 900
umount $MNT_POINT
test -f $DST_DIR/$DST_FILE && rm -f $DST_DIR/$DST_FILE
(cd $TMP_DIR ; tar -Szcf $DST_DIR/$DST_FILE ./$TMP_IMAGE )
rm -f $TMP_DIR/$TMP_IMAGE
if [ -f $TW_POST ]; then
HM=`date +%H:%M`
echo "disk image backup finished at $HM" > $TMP_FILE
$TW_POST $TMP_FILE
rm $TMP_FILE
fi
0 件のコメント:
コメントを投稿