Table of Contents

, ,

Эпичный скрипт бекапа mysql

Саппорт webazilla.com поставили клиенту скрипт резервирования баз mysql.
Конструкция WHICH_WHICH='which' заслуживает второго киселя и дополнительных 15 минут прогулки,
ветвление глубиной в 8 уровней - осиновый кол в серде, а акты непроизвольной обфускации смогут быть купированы только отрубанием верхних конечностей.

#!/bin/sh
# MySQL backup creation/rotation scenario

# =============== Config Section ====================<
BDIR='/home/backup'
DATADIR='/home/mysql'
DBA_PASSWORD=''
# >========== End Of Config Section ==================

# non-user serviceable settings
DATE=`date "+%Y-%m-%d"`
DATE_TOUCH=`date "+%Y%m%d0001"`
BEXT='.sql'
GZEXT='.gz'
TAREXT='.tar'
FULLBACKPREFIX='mysql-data'
NICENUM=19
CHMODBDIR='700'
CHMODSTORE='400'
BACKMTIME_COMPRESSED=8
BACKMTIME_STORED=14
BACKMINIMUMDAYS=3
TARGET_BACKUP='backup'
TARGET_CHECK='check'

# paths
export PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/local/mysql/bin"
WHICH_WHICH='which'
WHICH_FIND=`$WHICH_WHICH find` || 'find'
WHICH_BASENAME=`$WHICH_WHICH basename` || 'basename'
WHICH_NICE=`$WHICH_WHICH nice` || 'nice'
WHICH_MYSQLDUMP=`$WHICH_WHICH mysqldump` || 'mysqldump'
WHICH_TAR=`$WHICH_WHICH tar` || 'tar'
WHICH_GZIP=`$WHICH_WHICH gzip` || 'gzip'
WHICH_CHMOD=`$WHICH_WHICH chmod` || 'chmod'
WHICH_TOUCH=`$WHICH_WHICH touch` || 'touch'
WHICH_MKDIR=`$WHICH_WHICH mkdir` || 'mkdir'
WHICH_ECHO=`$WHICH_WHICH echo` || 'echo'
WHICH_UNAME=`$WHICH_WHICH uname` || 'uname'

# initialization
OSMARKER=`$WHICH_UNAME -s`
TARGET="$1"
[ "$TARGET" = "" ] && TARGET=$TARGET_BACKUP
db_list=''
db_list_notrecent=''
db_cnt=0
db_cnt_notrecent=0

# collecting database list
if [ -d "$DATADIR" ]; then
    for f in `$WHICH_FIND "$DATADIR" -maxdepth 1 -type d`; do
        if [ "$f" != "$DATADIR" ]; then
            db_list=$db_list" "`$WHICH_BASENAME $f`
            db_cnt=$(($db_cnt+1))
        fi
    done
fi

# section: backup
if [ "$TARGET" = "$TARGET_BACKUP" ]; then
    # preparing backup directory
    [ ! -d $BDIR ] && ( $WHICH_MKDIR "$BDIR" && $WHICH_CHMOD $CHMODBDIR "$BDIR" )
    [ ! -d $BDIR ] && return 1
    # database backup loop
    for db_name in ${db_list}; do
        if [ $db_name!='' ]; then
            db_file_name="$BDIR/$db_name.$DATE$BEXT"
            gz_file_name="$db_file_name$GZEXT"
            $WHICH_NICE -n $NICENUM $WHICH_MYSQLDUMP -q -p$DBA_PASSWORD $db_name > "$db_file_name"
            if [ -s "$db_file_name" ]; then
                $WHICH_NICE -n $NICENUM $WHICH_GZIP -f -S "$GZEXT" "$db_file_name"
                if [ -s "$gz_file_name" ]; then
                    $WHICH_CHMOD $CHMODSTORE "$gz_file_name"
                    $WHICH_TOUCH -c -t $DATE_TOUCH "$gz_file_name"
                    # performing rotation
                    for listfile_name in `$WHICH_FIND "$BDIR" -type f -iname "$db_name.*$BEXT$GZEXT" -mtime +$BACKMTIME_COMPRESSED`; do
                        if [ -s "$listfile_name" ]; then
                            [ "$listfile_name" != "$gz_file_name" ] && rm "$listfile_name"
                        else
                            rm "$listfile_name"
                        fi
                    done
                else
                    [ -f "$gz_file_name" ] && rm "$gz_file_name"
                fi
            else
                [ -f "$db_file_name" ] && rm "$db_file_name"
            fi
        fi
    done
    # full backup (just to be sure)
    store_file_name="$BDIR/$FULLBACKPREFIX.$DATE$TAREXT"
    $WHICH_NICE -n $NICENUM $WHICH_TAR cf "$store_file_name" "$DATADIR"
    if [ -s "$store_file_name" ]; then
        $WHICH_CHMOD $CHMODSTORE "$store_file_name"
        $WHICH_TOUCH -c -t $DATE_TOUCH "$store_file_name"
        for listfile_name in `$WHICH_FIND "$BDIR" -type f -iname "$FULLBACKPREFIX.*$TAREXT" -mtime +$BACKMTIME_STORED`; do
            [ "$listfile_name" != "$store_file_name" ] && rm "$listfile_name"
        done
    fi
# section: check
elif [ "$TARGET" = "$TARGET_CHECK" ]; then
    check_result=''
    check_status=1
    meolder_border=$(($BACKMINIMUMDAYS+1))
    if [ `$WHICH_FIND $0 \( -type f -or -type l \) \( -atime +$meolder_border -or -mtime +$meolder_border \)` ]; then
        # collecting list of databases which are not recent
        if [ -d "$DATADIR" ]; then
            atime_border=$(($BACKMINIMUMDAYS+1))
            if [ $OSMARKER = "FreeBSD" ]; then
                atime_crit='Btime'
            else
                atime_crit='atime'
            fi
            for f in `$WHICH_FIND "$DATADIR" -maxdepth 1 -type d -$atime_crit +$atime_border`; do
                if [ "$f" != "$DATADIR" ]; then
                    db_list_notrecent=$db_list_notrecent" "`$WHICH_BASENAME $f`
                    db_cnt_notrecent=$(($db_cnt_notrecent+1))
                fi
            done
            db_cnt_new=$(($db_cnt-$db_cnt_notrecent))
            check_result="OK - healthy backups, databases: $db_cnt_new/$db_cnt (new/total)"
            check_status=0
        else
            check_result="WARNING - Database directory does not exist: '$DATADIR'"
            check_status=1
        fi
        if [ -d "$BDIR" ]; then
            if [ $OSMARKER = "Linux" ]; then
                mtime_first=1
                mtime_last=$BACKMINIMUMDAYS
            else
                mtime_first=2
                mtime_last=$(($BACKMINIMUMDAYS+1))
            fi
            for db_name in ${db_list_notrecent}; do
                if [ $db_name!='' ]; then
                    cnt_healthy_backups=0
                    mtime_check=$mtime_first
                    while [ "$mtime_check" -le "$mtime_last" ]; do
                        search_result=`$WHICH_FIND "$BDIR" -type f -iname "$db_name.*$BEXT$GZEXT" \! -size 0 -mtime $mtime_check`
                        [ "$search_result" != "" ] && cnt_healthy_backups=$(($cnt_healthy_backups+1))
                        mtime_check=$(($mtime_check+1))
                    done
                    if [ "$cnt_healthy_backups" -lt "$BACKMINIMUMDAYS" ]; then
                        cnt_missing=$(($BACKMINIMUMDAYS-$cnt_healthy_backups))
                        check_result="CRITICAL - missing $cnt_missing backup(s) of database '$db_name'"
                        check_status=2
                        break
                    fi
                fi
            done
        else
            check_result="WARNING - Backup directory does not exist: '$BDIR'"
            check_status=1
        fi
    else
        check_result="OK - check has not been performed, it's new installation"
        check_status=0
    fi
    $WHICH_ECHO $check_result
    exit $check_status
fi