ファイヤープロジェクト
バックアップをCDRに焼く
2003-07-20T15:13+09:00   matsu
ここまでの記述をもとに,バックアップをCDRに焼くBASHスクリプトを作成してみる.
ここではバックアップをCDRに焼くスクリプトを作成する.仕様は以下のとうり.
目的
指定したディレクトリをバックアップとしてCDRに焼くためのものである.
対象
私.
使用方法
以下を順に実行する.
  • CDRメディアをCDRドライブに挿入する.メディアはサラかセッションを閉じていないものとする.
  • スクリプトを実行する.
    Usage   : /root/usr/bin/backup-cdr -d CDRDEVICE [-c] [-size MEDIASIZE] TARGET
    Usage   : /root/usr/bin/backup-cdr -h
    TARGET is file or directory you want to backup
    
    Options
             -c     : compress
             -d     : CD-R device
             -size MEDIASIZE 
                    : MEDIASIZE is size of media , and this program calculate rest size of media.Default MEDIASIZE is 650MB.
             -h     : show this message
    
本スクリプト使用による獲得物
CDRに上記targetディレクトリで指定したディレクトリのバックアップが作成される.CDRには,上記targetディレクトリをそのままの形で作成するか,tar.gzで固めて作成する.そのbasenameの頭に日付を付加した形式で作成される.
#!/bin/sh 
#デバッグ用
#set -x
#メディアのサイズを保存
MEDIASIZE=650
#圧縮するか否か.1なら圧縮
TGZFLAG=0
#バックアップ対象の絶対パス
TARGET=""
#isoファイルのサイズ
ISO_SIZE=""
#CDRデバイス
CDRDEVICE=""
#CDRをマウントするディレクトリ
MOUNTDIR=""
#作業用ディレクトリ
WD=/tmp
#作業用ファイル
WF=tmp-mount-err
#mountしたときのエラーメッセージ格納用
MOUNTERROR=""
#mountの際メディアがみつからかった場合にmountが吐くエラーメッセージ
MEDIA_NOT_FOUND_ERROR="メディアが見つかりません"
#サラのCDRか否か
MULTI_FLAG=""
#mountの際wrong fs typeだった場合にmountが吐くエラーメッセージ.これをサラのメディアかどうかの判定に利用する
WRONG_FS_TYPE_ERROR="wrong fs type"
#cdrbus.cdrecordで使用
CDRBUS=$(cdrecord -scanbus 2>/dev/null | awk '/CDR/ {print $1}' -)

#デバッグ用
function printValues(){
	printf "MEDIASIZE=$MEDIASIZE
TGZFLAG=$TGZFLAG
TARGET=$TARGET
CDRDEVICE=$CDRDEVICE
DAYNAME=$DAYNAME
TGZNAME=$TGZNAME
ISONAME=$ISONAME
ISO_OPTION=$ISO_OPTION
REST_MEDIA_SIZE=$REST_MEDIA_SIZE
CDRBUS=$CDRBUS
"
}

#使用法を表示
function printUsage(){
			printf "Usage \t: $0 -d CDRDEVICE [-c] [-size MEDIASIZE] TARGET
Usage \t: $0 -h
TARGET is file or directory you want to backup

Options
\t -c \t: compress
\t -d \t: CD-R device
\t -size MEDIASIZE \n\t\t: MEDIASIZE is size of media , and this program calculate rest size of media.Default MEDIASIZE is 650MB.
\t -h \t: show this message\n"
}

#パラメータチェックを行う関数.
#-sizeや-cオプションがあれば,再帰呼び出しを行う.
function readParam(){
	case $1 in
		#-sizeオプションの取得
		-size)
		    case $2 in
			#-sizeの後に数値がきているかどうかのチェック.
			[0-9]*)
			    MEDIASIZE=$2
			    shift 2
			    readParam $*
			    ;;
			*)
			    printUsage
			    exit 1
			    ;;
		    esac
		    ;;
		#-dオプションの取得
		-d)
			CDRDEVICE=$2
			MOUNTDIR=$(awk '/'$(basename $2)'/ {print $2}' /etc/fstab)
			shift 2
			readParam $*
			;;
		#-cオプションの取得
		-c)
			TGZFLAG=1
			shift 1
			readParam $*
			;;
		#-hオプションの取得
		-h)
			readParam undiefinedoption
			exit 0
			;;
		#/で始まるパラメータは必ずバックアップ対象.
		#これは必ず最後のパラメータなので(そういう仕様),再帰呼び出しの基底条件になる.
		/*)
			#指定されたディレクトリかファイルがある
			if [ -d $1 -o -f $1 ] ;then
				TARGET=$1
			#指定されたディレクトリかファイルがない
			else 
			printf "No such file or directory : $1\n"
				exit 1
			fi
			;;
		#この分岐に入るということは,バックアップ対象が指定されていない
		"")
			printf "Input target file or directory.\n\n"
			printUsage
			exit 1
			;;
		#残りは不正なパラメータ
		*)
			printUsage
			exit 1
			;;
	esac
}

#必要なパラメータが与えられているかどうかをチェック
function checkParam(){
	#TARGETが空文字列でないか.readParam関数によって,この分岐に入ることはない(一応書いてみた).
	if [ -z "$TARGET" ] ; then
		printf "Input target file or directory.\n\n"
		printUsage
		exit 1
	fi
	#CDRDEVICEが空文字列でないか
	if [ -z "$CDRDEVICE" ] ; then
		printf "Input CD-R device\n\n"
		printUsage
		exit 1
	fi
}

function setFileName(){
	#日付(年月日)
	DAYNAME=$(date -I)
	if [ "$TGZFLAG" -eq 1 ] ; then
	    #作成するtar.gzファイル名
	    TGZNAME=${DAYNAME}-$(basename $TARGET).tgz
	    #作成するisoイメージ名
	    ISONAME=${TGZNAME}.iso
	else
	    #作成するisoイメージ名
	    ISONAME=${DAYNAME}.iso
	fi
}

#作業用ディレクトリWDにisoイメージを作製する
function makeISOFile(){
	cd $WD
	if [ "$MULTIFLAG" -eq 1 ] ; then
	    ISO_OPTION="-r -nobak -M $CDRDEVICE -C $(cdrecord -msinfo dev=$CDRBUS)"
	else
	    ISO_OPTION="-r"
	fi
	if [ -n "$TGZNAME" ] ; then
	    #isoイメージの元になる圧縮ファイルを作る
	    tar zcvf $TGZNAME $TARGET &&
	    mkisofs $ISO_OPTION -o $ISONAME $TGZNAME || { printValues ; exit 1; }
	else
	    test -f $DAYNAME-$(basename $TARGET) || test  -d $DAYNAME-$(basename $TARGET)  || mkdir $DAYNAME-$(basename $TARGET)
	    cd $DAYNAME-$(basename $TARGET) &&
	    #isoイメージの元になるディレクトリを作る
	    cp -au $TARGET $DAYNAME-$(basename $TARGET) &&
	    cd ..
	    mkisofs $ISO_OPTION -o $ISONAME ${DAYNAME}-$(basename $TARGET) || { printValues ; exit 1; }
	fi
}

function checkMedia(){
	mount $CDRDEVICE 2> $WD/$WF
	#メディアの有無の確認
	MOUNTERROR=$(awk '/'"$MEDIA_NOT_FOUND_ERROR"'/ {print "'"$MEDIA_NOT_FOUND_ERROR"'"}' $WD/$WF)
	if [ "$MOUNTERROR" = "$MEDIA_NOT_FOUND_ERROR" ];then
	    printf "$CDRDEVICE に $MEDIA_NOT_FOUND_ERROR\n"
	    exit 1
	fi
	#マルチセッションかどうかの確認
	MULTIFLAG=$(awk '/'"$WRONG_FS_TYPE_ERROR"'/ {print "'"$WRONG_FS_TYPE_ERROR"'"}' $WD/$WF)
	if [ -n "$MULTIFLAG" ] ;then
	    MULTIFLAG=0
	else
	    MULTIFLAG=1
	fi
}

function checkMediaSize(){
	#メディアの空きサイズの確認
	ISO_SIZE=$(du -sm $WD/$ISONAME | awk '{print $1}' -)
	if [ "$MULTIFLAG" -eq 0 ] ; then
	    REST_MEDIA_SIZE=$MEDIASIZE
 	else 
	    let REST_MEDIA_SIZE=$MEDIASIZE-$(du -sm $MOUNTDIR | awk '{print $1}' -)
	    #メディアの空き容量が足りない場合
	    if [ "$REST_MEDIA_SIZE" -lt "$ISO_SIZE" ] ; then
		printf "Rest media size is not enough\n
\tRest media size\t: $REST_MEDIA_SIZE\n
\tISO image of target size\t: $ISO_SIZE\n"
		exit 1
	    fi
	fi

}

function makeCDR(){
    cd $WD
    cdrecord -v speed=8 dev=$CDRBUS  -multi -data $ISONAME
}

readParam $*
checkParam
setFileName
checkMedia
makeISOFile
checkMediaSize
makeCDR
#printValues
matsu(C)
Since 2002
Mail to matsu