一个清理脚本的改进思路(r5笔记第51天)
前几天同事问我一个问题,说在unix环境下有个目录下的文件/文件夹太多了,已经报了开始报系统错误了,客户希望能够定时进行这些目录的清理。
我连到那个环境去查看,ls都需要等待很长时间没有反应,最后尝试使用find命令,根据文件名来查找的时候反应才相对要快一些。
同事计划使用crontab来实现。
使用的命令大体如下:
59 23 1 1,4,7,10 * find /xxxx/tmp -mtime +90 -type d -print|xargs rm –rf
其中关键的地方是使用了xargs,根据我之前的测试,发现xargs在大批量的文件过滤时,效果还是不能让人满意的,而且在命令最后接入rm -rf,如果出现什么纰漏,那影响可就大了。 所以开始我是不建议直接这么用的。
根据分析,发现其实在几个目录下药删除的文件目录命名规则都比较固定。
比如是20141201的日志,命名就类似下面的形式。
container-default-instanceJob-201412001_xxxxxx
其中变化的部分主要是时间的部分,所以决定使用find -name的方式效果要好一些,但是find -name结合xargs的时候如果文件比较多,删除的时候还是有问题,而且rm -rf的潜在隐患还是有。
一种比较直接的方式就是我们生成对应的文件目录名,如果匹配,则删除,如果不匹配,也不会报出错误。
比方说我们根据需要删除字2014年12月1日起某些天的记录,则可以手工指定对应的文件名和时间戳。
rm -rf /xxxx/tmp/container-default-instanceJob-20141202*
rm -rf /xxxx/tmp/container-default-instanceJob-20141203*
rm -rf /xxxx/tmp/container-default-instanceJob-20141204*
rm -rf /xxxx/tmp/container-default-instanceJob-20141205*
rm -rf /xxxx/tmp/container-default-instanceJob-20141206*
rm -rf /xxxx/tmp/container-default-instanceJob-20141207*
这种方式会避免不少的问题,删除速度是没有问题的。而且可以避免很多意外的情况。
但是缺点就是太手动了,感觉没什么技术含量。
我们来把这个过程自动化一下。能够动态生成对应的文件目录名,每次运行之后都会把基准的时间重新调整。
比如我们删除60天的记录,假设起始时间为20141201,则60天后就是20150130,第二次运行这个命令就会把起始时间自动调整为20150130,终止时间就是20150331了。
第一次运行命令后,生成的删除命令为:
rm -rf /xxxx/tmp/container-default-instanceJob-20141202*
....
rm -rf /xxxx/tmp/container-default-instanceJob-20150130*
第二次运行同样的命令,生成的删除命令为:
rm -rf /xxxx/tmp/container-default-instanceJob-20150130*
....
rm -rf /xxxx/tmp/container-default-instanceJob-20150331*
这种方式就比较动态了,而且删除起来也是一个很稳定的过程。
首先采用shell的形式写了如下的脚本。
GetIncDate()
{
L_DAY=$1
days=$2
L_TODAY=$(printf "%(%Y%m%d)Tn" "${L_DAY}0000 + ${days} day")
print ${L_TODAY}
}
function gen_clean_script
{
for i in {1..$duration}
do
echo 'rm -rf /xxxxx/tmp/container-default-instanceJob-'`GetIncDate $initdate $i` >> gen_clean_script.sh
done
}
这种方式基于Linux环境实现,可以灵活的使用date命令的选项进行时间的计算。 但是问题来了,在Linux下可行的方案在unix底下没有那些个命令选项。也就是说这个shell脚本在unix下运行不了。问题还是基于一些命令的兼容性。 最后尝试把时间的计算用sql来实现,这样也不会存在平台的限制。 写出的基于sql计算时间的shell脚本如下:
function gen_clean_script
{
conn_str=$3
print "
conn $conn_str
set linesize 200
set serveroutput on
set feedback off
begin
for i in 1..$2 loop
dbms_output.put_line('rm -rf /xxxxx/tmp/container-default-instanceJob-'||to_char(to_date('$1','yyyymmdd')+i,'yyyymmdd')||'*');
end loop;
end;
/
" |sqlplus -s /nolog > gen_clean_script.sh
}
function get_next_date
{
conn_str=$3
print "
conn $conn_str
set serveroutput on
set feedback off
begin
dbms_output.put_line(to_char(to_date('$1','yyyymmdd')+$2,'yyyymmdd'));
end;
/
" |sqlplus -s /nolog > init.date
}
conn_str=n1/n1@xxxx
duration=60
if [[ ! -s init.date ]] ;then
echo '***********************************************'
echo '20141201' > init.date
initdate=20141201
echo $initdate
echo '***********************************************'
else
initdate=`cat init.date`
fi
gen_clean_script $initdate $duration $conn_str
get_next_date $initdate $duration $conn_str
cat gen_clean_script.sh
问题的解决就有了一种相对比较可行的思路,这种方案有一个缺点就是需要连接数据库,不过对于数据库用户的配置没有其它要求,只要能运行sql查询即可。
- Nagios:企业级系统监控方案
- 从零开始搭建前端数据监控系统(一)-同类产品调研
- Kafka剖析系列之高可用(上)
- 大量图片优化
- ASP.NET 4.0 URL Routing HTTP Error 404.0 - Not Found
- 从零开始搭建前端数据监控系统(二)-前端性能监控方案调研
- 14个你可能不知道的JavaScript调试技巧
- Kafka剖析系列之高可用(下)
- 11 个简单的 Java 性能调优技巧
- NativeScript工作原理
- 如何合并Git 代码库中牛人的代码到自己的库
- Kafka剖析系列之Consumer解析
- android之View绘制
- 高性能JavaScript-JS脚本加载与执行对性能的影响
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python字符串split及rsplit方法原理详解
- Laravel框架文件上传功能实现方法示例
- python中如何写类
- 什么是PHP7中的孤儿进程与僵尸进程
- Python爬虫小例子——爬取51job发布的工作职位
- 详解PHP素材图片上传、下载功能
- Python enumerate() 函数如何实现索引功能
- python打开文件的方式有哪些
- PHP实现二维数组按照指定的字段进行排序算法示例
- python怎么自定义捕获错误
- Codeforces Round #677 (Div. 3)
- PHP PDOStatement::fetchObject讲解
- PHP PDOStatement::getAttribute讲解
- Laravel框架自定义验证过程实例分析
- Codeigniter里的无刷新上传的实现代码