方法一
shell脚本如下:
#!/bin/bash
#日志文件路径
logPath=/var/log/yx.log
echo -e "$(date +%Y%m%d" "%H:%M:%S): 清理程序开始执行!清理规则:A.文件大于100M,且存在时间超过5天;B.模型目录下的子目录存在时间超过30天
!
"
echo -e "$(date +%Y%m%d" "%H:%M:%S): 清理程序开始执行!清理规则:A.文件大于100M,且存在时间超过5天;B.模型目录下的子目录存在时间超过30天!
" >> $logPath
#计数器,计算总共删除了多少个目录
dirCnt=0
#计数器,计算总共删除了多少个文件
fileCnt=0
function recursive() {
#dir="$1"
#if [ "$dir" == "" ];then
# echo 请输入一个参数,指定要清理的目录!
#else
#currDir=$1
#判断参数$1,是否以 / 结尾
#if [[ "$currDir" != */ ]];then
# #echo 当前目录/文件:${1%%/}
# currDir=$currDir"/"
#fi
echo -e "当前目录:$1"
echo -e "当前目录:$1" >>$logPath
#lines="`ls -l --time-style='+%Y%m%d' $1 | awk '{print $2,$6,$7,$1$8}'`"
#while循环位于管道中,这意味着在运行过程中,while循环实际是位于一个新的SHELL中的,while循环中的变量和文件开头定义的变量是两个不同的变量,所以while循环中所改变的值在while循环结束后无法保存下来。解决这个问题的方法就是不要使用管道,改用重定向!
while read line
do
#echo $line
#oldIFS=$IFS
#IFS=" " #设置字符串的分隔符为空格,默认为空格,所以这里不需要设置
arr=($line)
#echo " ${#arr[@]} ${arr[@]}"
if [[ "${arr[0]:0:1}" == "d" ]];then
#文件创建/修改日期距离当前日期的天数
diffDays=$((($(date +%s) - $(date +%s -d ${arr[2]}))/86400))
#判断当前目录是否是模型目录下的子目录,比如/data/xwd/20191102/,且存在时间超过30天,超过则删除
if [[ "${arr[3]}" =~ ^[0-9]{4}(0[0-9]|1[12])([012][0-9]|3[01])$ && $diffDays -gt 30 ]];then
rm -rf $1/${arr[3]}
echo " $1/${arr[3]}:该目录存在时间超过30天,删除之"
echo " $1/${arr[3]}:该目录存在时间超过30天,删除之" >> $logPath
let dirCnt++
#否则,递归处理下一个目录
else
if [[ "$1" != */ ]];then
recursive $1/${arr[3]}
else
recursive $1${arr[3]}
fi
fi
elif [[ "${arr[0]:0:1}" == "-" ]];then
#echo " $1/${arr[3]}"
#如果文件存在天数大于60天,则删除(该条规则目前作废)
#if [ $diffDays -gt 60 ];then
# echo " $1/${arr[3]}:该文件存在时间超过60天,删除之"
# rm -f $1/${arr[3]}
# let fileCnt++
#文件创建/修改日期距离当前日期的天数
diffDays=$((($(date +%s) - $(date +%s -d ${arr[2]}))/86400))
#如果文件大于100M(104857600字节),且存在时间超过5天,则删除
if [[ ${arr[1]} -gt 104857600 && $diffDays -gt 5 ]];then
rm -f $1/${arr[3]}
echo " $1/${arr[3]}:该文件大于100M,且存在时间超过5天,删除之"
echo " $1/${arr[3]}:该文件大于100M,且存在时间超过5天,删除之" >> $logPath
let fileCnt++
fi
fi
done <<< "`ls -l --time-style='+%Y%m%d' $1 | awk '{print $1,$5,$6,$7}'`"
#fi
}
if [[ "$1" == "" ]];then
echo -e "请输入一个参数,指定要清理的目录!
"
echo -e "请输入一个参数,指定要清理的目录!
" >> $logPath
exit 1
else
recursive $1
fi
if [[ $dirCnt -eq 0 && $fileCnt -eq 0 ]];then
echo -e "
$(date +%Y%m%d" "%H:%M:%S): 清理程序执行完毕!没有要删除的文件!
"
echo -e "
$(date +%Y%m%d" "%H:%M:%S): 清理程序执行完毕!没有要删除的文件!
" >> $logPath
else
echo -e "
$(date +%Y%m%d" "%H:%M:%S): 清理程序执行完毕!共删除了 ${dirCnt} 个目录,和 ${fileCnt} 个文件!
"
echo -e "
$(date +%Y%m%d" "%H:%M:%S): 清理程序执行完毕!共删除了 ${dirCnt} 个目录,和 ${fileCnt} 个文件!
" >> $logPath
fi
exit
方法二
#还未全部测试
#删除大于100M,且超过5天的文件
find . -size +100M -mtime +5 -type f -exec ls -alh {} >> yx.log;
find . -size +100M -mtime +5 -type f -exec rm -rf {} ;
#删除超过30天的文件夹
find /data -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec ls -ahl15 {} ;
find /data -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec rm -rf {} ;
一、过程中涉及的知识:
1、
查看当前目录的总大小
sudo du -sh .
查看当前目录下的所有子目录和子文件的总大小
sudo du -sh *
查看指定目录的总大小
sudo du -sh data/
2、普通的shell脚本使用以下语句作为第一行:
/bin/bash
3、修改文件/文件夹的修改时间:
touch -mt 1901020905 file1
4、ls 查看格式化后的时间:
ll --time-style='+%Y%m%d %H:%M:%S'
-rw-r----- 1 weblogic weblogic 5557932 20190102 09:05:00 aaa.txt
5、日期的格式化:
- 特定日期转化为时间戳,即距离1970.01.01 08:00的秒数:
$(date +%s -d '20120101') #结果为:1325347200 - 当天和指定日期之间相隔的天数:
diffDays=$((($(date +%s) - $(date +%s -d '20120101'))/86400)) - 格式化当前日期:
echo $(date +%Y%m%d" "%H:%M:%S) #结果是:20191205 13:56:24
6、单、双括号运算符:
shell单括号运算符号:
a=$(date);
等同于:a=date
;
双括号运算符:
a=$((1+2));
echo $a;
等同于:
a=expr 1 + 2
7、awk知识:
- 在awk中,输入文本的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。awk工作流程是这样的:读入有' '换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。
- -F ':' 指定输入值的域分隔符(field-separator)为英文冒号 :
eg. ls -l --time-style='+%Y%m%d' $1 | awk '{print $1,$5,$6,$7}'
在ls -l列出的文件列表信息中,打印第1、5、6、7个域
8、echo命令: -e 开启转义
eg. echo -e "请输入一个参数,指定要清理的目录!
"
注:
表示换行符。
9、数组:
- echo ${#arr[@]} #打印数组包含元素的个数
- echo ${arr[@]} #打印数组的所有元素
- echo ${arr[0]:0:1} #数组中某个元素从索引0开始截取1个字符,然后打印
- shell 字符串转换为数组:
line="a,b,c"
oldIFS=$IFS
IFS=, #设置字符串的分隔符为英文逗号,不设置的话默认为空格
arr=($line)
10、shell中不能使用别名,如ll等。
11、vim中全局替换,其中包含了转义符号 :
:%s//var/log/yx.log/$logPath/g
二、过程中出现的错误:
1、Shell脚本报错:
/usr/local/bin/cleanData.sh: line 32: [: ==: unary operator expected
原因:在匹配字符串时用了类似这样的语句:
if[ $timeofday = "yes" ] ...
如果变量timeofday的值为空,那么就if语句就变成了if [ = "yes" ],这不是一个合法的条件。为了避免出现这种情况,我们必须给变量加上引号if [ "$timeofdat" = "yes" ],这样即使是空变量也提供了合法的测试条件,if [ " " = "yes" ]
2、Shell脚本报错:
cleanData.sh: line 63: [: missing `]'
其中,63行代码为:if [ ${arr[1]} -gt 104857600 && $diffDays -gt 7 ];then
原因:if使用了单个括号,需要使用双括号。
小结:网上还有一个错误原因是if ["$NGINX_FLAG" = '1'],"$NGINX_FLAG"之前和'1'之后没有空格,两个都要有空格。
另外,字符串的if语句比较最好使用双括号。他支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。