shell的一个不错的定期清理脚本

最近写了一个删除脚本,用于定期删除某些文件夹中的数据,该脚本需要如下参数:
①设置删除的目录
②该目录最少保留的时间,如3天
③该目录最多保留的时间,如30天
④该目录最大空间大小,如10G
⑤该目录所在磁盘分区的最大使用量,如80%
以上三个条件只要满足其中一条,便开始删除目录中30天前的数据,然后检查,若仍然满足,则继续删除29天前的数据,如此循环,直至磁盘分区使用量小于80%
改进:刚开始使用的是exit,但是这有个问题就是,如果要定期清理多个目录,就无法满足需求了,因为检查了第一个目录整个脚本就exit退出,而用return就ok,只会退出当前函数,会继续检查下一个目录
以下是脚本内容:粗略测试了一下,没什么问题,欢迎大家一起测试

最近做了个改版的,取消设置目录最大大小,触发条件仅为分区使用量,因为设置最大目录大小感觉很鸡肋

#!/bin/bash
:<<block
    author:@michaelzeng
    date:2016-04-27
block
loglevel=0 #debug:0; info:1; warn:2; error:3
logdir=/data/logs/diskchk
logfile=${logdir}/diskchk.log
test -d $logdir || mkdir -p $logdir
function log {
    local msg;local logtype
        logtype=$1
        msg=$2
        datetime=`date +'%F %H:%M:%S'`
        logformat="[${logtype}]\t${datetime}\tfuncname: ${FUNCNAME[@]/log/} [line:`caller 0 | awk '{print$1}'`]\t${msg}"
        {
        case $logtype in
                debug)
                        [[ $loglevel -le 0 ]] && echo -e "\033[30m${logformat}\033[0m" ;;
                info)
                        [[ $loglevel -le 1 ]] && echo -e "\033[32m${logformat}\033[0m" ;;
                warn)
                        [[ $loglevel -le 2 ]] && echo -e "\033[33m${logformat}\033[0m" ;;
                error)
                        [[ $loglevel -le 3 ]] && echo -e "\033[31m${logformat}\033[0m" ;;
        esac
        } >> $logfile
        #} | tee -a $logfile
}

function check()
{
    #检查目录,确保目录不在以下目录,以免被误删
    notdeldir='/ /boot /boot/ /var /var/ /lib/ /lib /etc /etc/ /bin /bin/ /lib64  /lib64/ /usr/ /usr  /apps /apps/ /boot_ucloud /boot_ucloud/ /data /data/ /dev /dev/ /home /home/ /lost+found /lost+found/ /media /media/ /mnt /mnt/ /opt /opt/ /proc /proc/ /root /root/ /sbin /sbin/ /selinux /selinux/ /srv /srv/'
    local src_dir=$1
    for blackdir in $notdeldir;
    do
        if [[ $src_dir == $blackdir ]];then
            log error "$src_dir:can't delete this directory"
            return 10
        fi
    done
    return 0
}
function chkuse()
{
    local src_dir=$1
    local partition;local par_size;local disk_ppc
    partition=`df -Ph $src_dir|awk '/dev/{print $6}'`
    par_size=`df -Ph $src_dir|awk '/dev/{print $2}'|tr -d G`
    disk_ppc=`df -Ph $src_dir|awk '/dev/{print $5}'|tr -d %`
    if [ ${disk_ppc} -le ${use} ]; then
        log info "partition:$partition; use:${disk_ppc}%,$src_dir dir is ok"
        return 1
    else
        log info "partition:$partition; use:${disk_ppc}%,we will clean dir:$src_dir"
        return 0
    fi
}
function clean()
{   
    #满足删除条件时,删除文件直到分区用量小于$use
    paracount=3
    if [ $# -eq $paracount ]; then
        local src_dir=$1
        local min_tmd=$2
        local max_tmd=$3
    else
        return 1
    fi
    local disk_ppc=0
    #目录所在分区,分区大小,分区已用量
    chkuse $src_dir
    if [ $? -eq 1 ]; then
        #log debug "disk:$partition; use:${disk_ppc}%,no need to clean"
        return 4
    else
        local delfile
        delfile=$(find ${src_dir} -type f -mtime +${max_tmd})
        if [[ -n $delfile ]];then
            log debug "delete file ${max_tmd} days ago;in dir:$src_dir;delete file : $delfile"
            for file in $delfile;do rm -f $file;done
            #for file in $delfile;do echo $file;done
        fi
    fi
}
# MIN_TMD 保留最短时间(天为单位)
# MAX_TMD 保留最长时间(天为单位)
function do_clean()
{
    PARACOUNT=3
    if [ $# -eq $PARACOUNT ]; then
        local SRC_DIR=$1
        local MIN_TMD=$2
        local MAX_TMD=$3
    else
        echo "Usage: ${FUNCNAME[@]} <SRC_DIR> <MIN_TMD> <MAX_TMD>"
        log debug "need $PARACOUNT parameters,but give:$#"
        return 1
    fi
    if [ ${MAX_TMD} -lt ${MIN_TMD} ]; then
        log debug "para MAX_TMD should be biger than MIN_TMD"
        return 2
    fi
    if [ ! -d "$SRC_DIR" ];then
        log debug "$SRC_DIR: No such directory"
        return 3
    fi
    check $SRC_DIR
    if [ $? -eq 0 ];then
        #删除大于$MAX_TMD天的文件
        local delfile
        delfile=$(find ${SRC_DIR} -type f -mtime +${MAX_TMD})
        if [[ -n $delfile ]];then
            log debug "delete file that ${MAX_TMD} days ago,in dir:$SRC_DIR,file:${delfile}"
            for file in $delfile;do rm -f $file;done
            #for file in $delfile;do echo $file;done
        fi
        #开始循环检查
        chkuse ${SRC_DIR}
        if [[ $? -eq 0 ]];then
            ((TM=MAX_TMD))
            COUNT=$(( MAX_TMD-MIN_TMD ))
            for(( i=0; i<=COUNT;i++ ))
            do
                clean "$SRC_DIR" "$MIN_TMD" "$TM"
                if [ $? -eq 4 ]; then
                    break
                fi
                if [ ${TM} -gt ${MIN_TMD} ]; then
                    (( TM=TM-1 ))
                else
                    #达到最少保留天数限制,则找出大于8G的大文件,清空
                    log warn "still not enough space,we will find the big file and clean it"
                    bigfile=$(find ${SRC_DIR} -type f -size +${max_filesize})
                    if [[ -n $bigfile ]];then
                        log debug "clean the filesize -gt ${max_filesize},bigfile is $bigfile"
                        for f in $bigfile;do echo '' > $f;done
                        chkuse ${SRC_DIR}
                        break
                    fi
                fi
            done
        fi
    fi
}
##################  main  ###################
#举个栗子:/var/spool/clientmqueue/目录,最少保留3天,最多保留30天
use=75 #定义某分区最大使用量
max_filesize=8G #定义最大文件大小,当达到最少保留天数限制时,清空该文件
#do_clean /var/spool/clientmqueue/ 3 10
do_clean /data/logs/ 3 10
do_clean /data/backup/ 3 10

最初版本:

#!/bin/bash
:<<block
    author:@michaelzeng
    date:2016-04-27
block
use=30 #定义某分区最大使用量
loglevel=0 #debug:0; info:1; warn:2; error:3
logfile=${0%.*}".log"
function log {
        local msg;local logtype
        logtype=$1
        msg=$2
        datetime=`date +'%F %H:%M:%S'`
        #logformat="[${logtype}]\t${datetime}\tfuncname:${FUNCNAME[@]}\t[line:$LINENO]\t${msg}"
        logformat="[${logtype}]\t${datetime}\tfuncname: ${FUNCNAME[@]/log/} [line:`caller 0 | awk '{print$1}'`]\t${msg}"
        {
        case $logtype in
                debug)
                        [[ $loglevel -le 0 ]] && echo -e "\033[30m${logformat}\033[0m" $logflag;;
                info)
                        [[ $loglevel -le 1 ]] && echo -e "\033[32m${logformat}\033[0m" $logflag;;
                warn)
                        [[ $loglevel -le 2 ]] && echo -e "\033[33m${logformat}\033[0m" $logflag;;
                error)
                        [[ $loglevel -le 3 ]] && echo -e "\033[31m${logformat}\033[0m" $logflag;;
        esac
        #} >> $logfile
        } | tee -a $logfile
}

function check()
{
    #检查目录,确保目录不在以下目录,以免被误删
    notdeldir='/ /boot /boot/ /var /var/ /lib/ /lib /etc /etc/ /bin /bin/ /lib64  /lib64/ /usr/ /usr  /apps /apps/ /boot_ucloud /boot_ucloud/ /data /data/ /dev /dev/ /home /home/ /lost+found /lost+found/ /media /media/ /mnt /mnt/ /opt /opt/ /proc /proc/ /root /root/ /sbin /sbin/ /selinux /selinux/ /srv /srv/'
    local src_dir=$1
    for blackdir in $notdeldir;
    do
        if [[ $src_dir == $blackdir ]];then
            log error "$src_dir:can't delete this directory"
            return 10
        fi
    done
    return 0
}
function clean()
{   
    #满足删除条件时,删除文件直到分区用量小于$use
    paracount=4
    if [ $# -eq $paracount ]; then
        local src_dir=$1
        local min_tmd=$2
        local max_tmd=$3
        local max_dsk=$4
    else
        return 1
    fi
    local disk_ppc=0
    #目录所在分区,分区大小,分区已用量
    partition=`df -Ph $src_dir|awk '/dev/{print $6}'`
    par_size=`df -Ph $src_dir|awk '/dev/{print $2}'|tr -d G`
    disk_ppc=`df -Ph $src_dir|awk '/dev/{print $5}'|tr -d %`
    if [ ${disk_ppc} -le ${use} ]; then
        log debug "disk:$partition; use:${disk_ppc}%,no need to clean"
        return 4
    fi
    #检查设置的目录最大大小是否小于分区的$use%
    max_use=$((par_size*use/100))
    if [ $max_dsk -gt $max_use ];then
        #echo "目录最大使用量设置错误,需小于所在分区大小的${use}%"
        #max_dsk改为分区大小的${use}%
        log warn "parameter MAX_GB:$max_dsk > ${par_size}*${use}/100,set default:par_size*use/100"
        max_dsk=$max_use
    fi
    #目录大小
    local src_dir_sz=`du --summarize --block-size=1G ${src_dir} | awk '{print $1}'`
    if [ ${src_dir_sz} -gt ${max_dsk} ]; then
        #找出${src_dir}中${max_tmd}天前以日期命名的目录并删除直到,${src_dir}空间大小小于${max_dsk} 
        local delfile
        delfile=$(find ${src_dir} -type f -mtime +${max_tmd} | egrep "`date +%Y`")
        log debug "in dir:$src_dir;delete file : $delfile"
        #find ${src_dir} -type f -mtime +${max_tmd} | egrep "`date +%Y`" |xargs -i rm -f {}
    else
        return 5
    fi
}
# MIN_TMD 保留最短时间(天为单位)
# MAX_TMD 保留最长时间(天为单位)
# MAX_GB 目录最多存储空间(GB为单位)
# 清理数据按1小时清理直到空间小于MAX_GB
function do_clean()
{
    PARACOUNT=4
    if [ $# -eq $PARACOUNT ]; then
        local SRC_DIR=$1
        local MIN_TMD=$2
        local MAX_TMD=$3
        local MAX_GB=$4
    else
        echo "Usage: ${FUNCNAME[@]} <SRC_DIR> <MIN_TMD> <MAX_TMD> <MAX_GB>"
        log debug "need $PARACOUNT parameters,but give:$#"
        return 1
    fi
    if [ ${MAX_TMD} -lt ${MIN_TMD} ]; then
        log debug "para MAX_TMD should be biger than MIN_TMD"
        return 2
    fi
    if [ ! -d "$SRC_DIR" ];then
        log debug "$SRC_DIR: No such directory"
        return 3
    fi
    check $SRC_DIR
    if [ $? -eq 0 ];then
        #删除大于$MAX_TMD天的文件
        local delfile
        delfile=$(find ${SRC_DIR} -type f -mtime +${MAX_TMD} | egrep "`date +%Y`")
        [[ -n $delfile ]] && log info "delete file that ${MAX_TMD} days ago,in dir:$SRC_DIR,file:${delfile}"
        #开始循环检查
        (( TM=MAX_TMD ))
        for(( i=0; i<MAX_TMD; i++ ))
        do
            if [ ${TM} -gt ${MIN_TMD} ]; then
                (( TM=TM-1 ))
            else
                break
            fi
            log info "check dir:${SRC_DIR} that ${TM} days ago"
            clean "$SRC_DIR" "$MIN_TMD" "$TM" "$MAX_GB"
            if [ $? -eq 5 ]; then
                break
            fi
        done
    fi
}
##################  main  ###################
#举个栗子:/var/spool/clientmqueue/目录,最少保留3天,最多保留30天,最大1G
do_clean /var/spool/clientmqueue/ 3 30 1
do_clean /media 3 30 1 #禁止删除
do_clean /media/ 3 30 1 #禁止删除
#最大目录大小10G大于分区大小的最大使用量30%
do_clean /media/CentOS 3 30 10 
do_clean #参数错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值