write file
最近在优化一些shell脚本任务,涉及到对文件的读写过程,这里聊聊我碰到的一些问题。
我的脚本主要是对数据进行统计和计算,数据具有时序性,每分钟会有一行结果存在结果文件中。
脚本每分钟执行一次,每次计算上一分钟和当前分钟的结果。保存结果数据时,会涉及到删除结果文件的最后一行,因为最后一分钟会被修正。
如何衔接两次任务的时间
数据结果的文件每一行都对应一分钟的数据,每行开头都记录对应的时间戳。
每次任务开始时,都读取结果文件的末尾,计算合理的数据时间。
thishourday=`date "+%Y-%m-%d"`
startTime=`date -d "${thishourday}" +%s`
if [ -f "$rfile" ]; then
startTime=`tail -n 1 $rfile | awk '{print $1}'`
else
touch $rfile
fi
原始数据文件有DailyRolling
这就意味着每天00:00处理数据时,需要读取前一天的文件和当天文件。
starthourday=`date --date=@${startTime} "+%Y-%m-%d"`
if [ $starthourday = $thishourday ];then
dfile=$dfile
else
dfile=$dfile"-"$starthourday" "$dfile
fi
保存计算结果
每次计算任务完成后,都先将数据写入临时文件tfile中,接下来我们删除结果文件的最后一行。
删除我们用了一个简单的命令
sed -i '$ d' $rfile
最后我们将临时文件Merge到结果文件的末尾,删除临时文件。
cat $tfile >> $rfile
rm -rf $tfile
性能问题
如果结果文件越来越大,这个任务会越来越慢,主要的性能问题在删除文件最后一行这一步。
sed删除最后一行这样的方式,几乎等于把整个文件重写了一遍。有兴趣的朋友可以看看这篇Blog。
我觉得出现这个问题本身就代表了设计问题,临时数据(最后一行)是否要直接写入结果文件?
可以借鉴Compaction那样的思路,将不确定的临时数据写入临时文件,当可以确定时写入正式的结果文件中,规避性能问题。
最好还是把这些数据存入数据库吧,时序数据库千千万。