最近写了一个删除脚本,用于定期删除某些文件夹中的数据,该脚本需要如下参数:
①设置删除的目录
②该目录最少保留的时间,如3天
③该目录最多保留的时间,如30天
④该目录最大空间大小,如10G
⑤该目录所在磁盘分区的最大使用量,如80%
以上三个条件只要满足其中一条,便开始删除目录中30天前的数据,然后检查,若仍然满足,则继续删除29天前的数据,如此循环,直至磁盘分区使用量小于80%
改进:刚开始使用的是exit,但是这有个问题就是,如果要定期清理多个目录,就无法满足需求了,因为检查了第一个目录整个脚本就exit退出,而用return就ok,只会退出当前函数,会继续检查下一个目录
以下是脚本内容:粗略测试了一下,没什么问题,欢迎大家一起测试
最近做了个改版的,取消设置目录最大大小,触发条件仅为分区使用量,因为设置最大目录大小感觉很鸡肋
#!/bin/bash
:<<block
author:@michaelzeng
date:--
block
loglevel= #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 ]] && echo -e "\033[30m${logformat}\033[0m" ;;
info)
[[ $loglevel -le ]] && echo -e "\033[32m${logformat}\033[0m" ;;
warn)
[[ $loglevel -le ]] && echo -e "\033[33m${logformat}\033[0m" ;;
error)
[[ $loglevel -le ]] && 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
fi
done
return
}
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
else
log info "partition:$partition; use:${disk_ppc}%,we will clean dir:$src_dir"
return
fi
}
function clean()
{
#满足删除条件时,删除文件直到分区用量小于$use
paracount=
if [ $# -eq $paracount ]; then
local src_dir=$1
local min_tmd=$2
local max_tmd=$3
else
return
fi
local disk_ppc=
#目录所在分区,分区大小,分区已用量
chkuse $src_dir
if [ $? -eq ]; then
#log debug "disk:$partition; use:${disk_ppc}%,no need to clean"
return
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=
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
fi
if [ ${MAX_TMD} -lt ${MIN_TMD} ]; then
log debug "para MAX_TMD should be biger than MIN_TMD"
return
fi
if [ ! -d "$SRC_DIR" ];then
log debug "$SRC_DIR: No such directory"
return
fi
check $SRC_DIR
if [ $? -eq ];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 ]];then
((TM=MAX_TMD))
COUNT=$(( MAX_TMD-MIN_TMD ))
for(( i=; i<=COUNT;i++ ))
do
clean "$SRC_DIR" "$MIN_TMD" "$TM"
if [ $? -eq ]; then
break
fi
if [ ${TM} -gt ${MIN_TMD} ]; then
(( TM=TM- ))
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= #定义某分区最大使用量
max_filesize=G #定义最大文件大小,当达到最少保留天数限制时,清空该文件
#do_clean /var/spool/clientmqueue/ 3 10
do_clean /data/logs/
do_clean /data/backup/
最初版本:
#!/bin/bash
:<<block
author:@michaelzeng
date:--
block
use= #定义某分区最大使用量
loglevel= #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 ]] && echo -e "\033[30m${logformat}\033[0m" $logflag;;
info)
[[ $loglevel -le ]] && echo -e "\033[32m${logformat}\033[0m" $logflag;;
warn)
[[ $loglevel -le ]] && echo -e "\033[33m${logformat}\033[0m" $logflag;;
error)
[[ $loglevel -le ]] && 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
fi
done
return
}
function clean()
{
#满足删除条件时,删除文件直到分区用量小于$use
paracount=
if [ $# -eq $paracount ]; then
local src_dir=$1
local min_tmd=$2
local max_tmd=$3
local max_dsk=$4
else
return
fi
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 debug "disk:$partition; use:${disk_ppc}%,no need to clean"
return
fi
#检查设置的目录最大大小是否小于分区的$use%
max_use=$((par_size*use/))
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=G ${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
fi
}
# MIN_TMD 保留最短时间(天为单位)
# MAX_TMD 保留最长时间(天为单位)
# MAX_GB 目录最多存储空间(GB为单位)
# 清理数据按1小时清理直到空间小于MAX_GB
function do_clean()
{
PARACOUNT=
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
fi
if [ ${MAX_TMD} -lt ${MIN_TMD} ]; then
log debug "para MAX_TMD should be biger than MIN_TMD"
return
fi
if [ ! -d "$SRC_DIR" ];then
log debug "$SRC_DIR: No such directory"
return
fi
check $SRC_DIR
if [ $? -eq ];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=; i<MAX_TMD; i++ ))
do
if [ ${TM} -gt ${MIN_TMD} ]; then
(( TM=TM- ))
else
break
fi
log info "check dir:${SRC_DIR} that ${TM} days ago"
clean "$SRC_DIR" "$MIN_TMD" "$TM" "$MAX_GB"
if [ $? -eq ]; then
break
fi
done
fi
}
################## main ###################
#举个栗子:/var/spool/clientmqueue/目录,最少保留3天,最多保留30天,最大1G
do_clean /var/spool/clientmqueue/
do_clean /media #禁止删除
do_clean /media/ #禁止删除
#最大目录大小10G大于分区大小的最大使用量30%
do_clean /media/CentOS
do_clean #参数错误