3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(Linux)バックアップシェルスクリプトで世代管理1

ずいぶん前の記事、cron & シェルスクリプト でバックアップ用のシェルスクリプトを書きました。

設定ファイル(bksrc.dat)にバックアップ元ディレクトリパスと、バックアップ時の接頭ファイル名を定義し、ファイル名に日付を埋め込んでtgzファイルにバックアップするというものでした。

しかし、世代管理の仕組みをいれてなかったので、ずっとバックアップが溜まり続けます。

ということで、古くなったバックアップファイルを削除する処理、そしてエラーがあったらメールを飛ばす処理を追加してみました。

メインのバックアップスクリプト(/root/sh/bkup.sh)は下記のようになります。

#!/bin/sh

#このスクリプトのパスを取得

MYPATH=$(cd $(dirname $0);pwd)

#世代管理(何日分残すか)

DAYAGO="7"

#-------バックアップ処理-------

#バックアップ元ファイル読み込みパスと保存ファイル名読み込み、ループ開始

cat ${MYPATH}/bksrc.dat | grep -v \# | while read BKSRC_DIR_NAME BKTO_NAME

do

BKSRC=.$BKSRC_DIR_NAME

#日付・時刻取得し変数に代入

TIMESET=`date +%Y%m%d-%H%I%M`

#バックアップ先ファイル名を設定 設定ファイルにあるファイル名+日付.tar.gzする

BKFILE=${BKTO_NAME}.$TIMESET.tar.gz

cd /

if [ -d $BKSRC ]; then

#バックアップ対象がディレクトリの場合

cd $(dirname ${BKSRC})

#tarコマンドで元ディレクトリを圧縮(相対パス指定)

tar vzcf $BKFILE $(basename ${BKSRC})

else [ -f $BKSRC ]

#バックアップ対象がファイルの場合

cd $(dirname $(dirname $BKSRC))

#tarコマンドで元ディレクトリを圧縮(相対パス指定)

tar vzcf $BKFILE $(basename $(dirname ${BKSRC}))/$(basename ${BKSRC})

fi

#成功したらその旨を表示かつ、ログに保存

if [ $? = 0 ]; then

logger -t dir_bkup "Backup OK $BKFILE"

echo "Backup OK $BKFILE"

else

#失敗したらその旨を表示かつ、ログに保存、メール送信

logger -t dir_bkup "Backup NG $BKFILE"

echo "Backup NG $BKFILE"

${MYPATH}/mailsend.sh "hoge@hoge.com" "バックアップ失敗通知" "実行バックアップスクリプト: ${0}

バックアップ対象: ${BKSRC_DIR_NAME}

バックアップに失敗しました。"

fi

#アクセス権を変更

chmod 666 $BKFILE

#-------yyyymmdd形式のファイルから古い物を削除-------

# 削除しきい日付(yyyymmdd)を設定。(DAYAGO日前の日付求める)

tday=`date -d "${DAYAGO} day ago" +%Y%m%d`

# 対象Dir配下のファイル名をwhileに渡し「$list」となる

ls $(basename ${BKTO_NAME})|while read list

do

#ファイル名に「数字x8」が含まれている場合、

if [[ $list =~ [0-9]{8} ]] ; then

# $listから、「yyyymmdd」を取り出しepoch時間($fday)にする

fday=`expr $list : "${BKTO_NAME}\.\([0-9]\{8\}\).*.tar.gz"`

#ファイル名から取得した「yyyymmdd」が本日の「yyyymmdd」よりも小さい場合

if [ -n "$fday" ] && [ $fday -lt $tday ]; then

# echo する

#echo $list

#削除する

rm -f $(basename ${BKTO_NAME})/${list}

fi

fi

done

done

削除処理はシェルスクリプトで日付の文字列を比較できないでしょうか? - Yahoo!知恵袋の回答で上がってたのを使わせてもらいました。

ファイル名に8文字の数字があるかどうかをチェックし、あった場合、数値に変換して削除しきい日を比較し、しきい日より小さければ削除するというものです。

失敗したらメールを送るようにしてますが、mailsend.sh については、(Linux)シェルスクリプトでメールを送信するを参考にしてください。

設定ファイル(/root/sh/bksrc.dat)の書式は下記のような感じです。

バックアップ先絶対パス バックアップ先DIR+ファイル名の接頭語

/var/www/html /var/backup/htmldata

/var/www/svn /var/backup/subversion

世代管理としては、findでファイル自身の更新日時で比較する方法が多いですが、このようにファイル名の中の日付で比較できるのはいいですね。

上記スクリプトを cron で毎日実行するようにすれば日次バックアップが可能です。

上記スクリプトでは、バックアップしたファイル名に対して削除するかどうか判定してますが、ただ単に指定したディレクトリすべてのファイルを対象にしたい場合は下記のように正規表現を直せばOKです。

#!/bin/sh

BKDIR=/var/backup/day/

#-------yyyymmdd形式のファイルから古い物を削除-------

# 削除しきい日付(yyyymmdd)を設定

tday=`date -d "7 day ago" +%Y%m%d`

# 対象Dir配下のファイル名をwhileに渡し「$list」となる

ls $BKDIR|while read list

do

#ファイル名に「数字x8」が含まれている場合、

if [[ $list =~ [0-9]{8} ]]

then

# $listから、「yyyymmdd」を取り出しepoch時間($fday)にする

fday=`expr $list : ".*\([0-9]\{8\}\).*.tar.gz"`

#ファイル名から取得した「yyyymmdd」が本日の「yyyymmdd」よりも小さい場合

if [ -n "$fday" ] && [ $fday -lt $tday ]; then

# echo する

#echo $list

#削除する

rm -f ${BKDIR}/${list}

fi

fi

done