// get_ord_minute-shell获取分钟值的个位数-20150226
// since: 2015-02-26
// by: gipsa02
在日志处理系统中,有时我们会以10分钟为单位对日志进行切割,统计,分析,投递等操作.
为了方便操作和脚本的兼容性,我会让脚本每次都处理上一个整十分钟的内容.
如当前时间是 11:24,则上一个整十分钟就是 [11:10,11:20).
这样一来,脚本在一个整十分钟内,即便运行多次,结果都是一样的.
而且只要脚本每个整10分钟内运行一次即可,不必要求必须间隔10分钟,或者必须在固定分钟点上运行,对于参与zabbix投递的脚本来说这就比较重要.
目前采取的方案是先获取 当前时间的分钟值的个位数 ORD_MINUTE.
然后用当前时间减去(ORD_MINUTE+10)作为上一个整十分钟的开始,用当前时间减去 ORD_MINUTE作为结束.
就像这样:
LAST_10MINUTE_START=`date -d "- $(($ORD_MINUTE+10))" + "%H:%M"`
LAST_10MINUTE_END=`date -d "- $(($ORD_MINUTE))" + "%H:%M"`
就拿到了开始时间和结束时间.
这里在计算 ORD_MINUTE 时遇到过一些问题,如下.
最初使用取模:
ORD_MINUTE=$((`date +%M`%10))
测试OK,放到线上跑一段时间,发现有时会有问题.
日志里记录:arithmetic expression: expecting EOF: "09%10"
原来当分钟值为"0n(0<=n<=9)"时,上面的shell数学计算会把"0n"当作一个八进制数字.
而09是非法的八进制数字. 于是shell报错.
可以这样检测出这个bug:
for i in `seq 60`; do
echo "i=$i"
ORD_MINUTE=$((`date -d "- $i minute" +%M`%10))
echo "$ORD_MINUTE"
done
当时为了简单,没有考虑使用复杂的数学计算.就使用sed把分钟值的第一位数字直接删除,相当于模10.
ORD_MINUTE=`date +%M | sed 's/^.//'`
但是增加了一步sed调用.
后来发现date原来可以不输出填充0的,于是还用shell取模做:
ORD_MINUTE=$((`date +%-M`%10))
格式化字符串 %M 变成了 %-M,则date在输出是不用0填充.
使用%_M 则用空格填充. 更多信息参见date手册.
手册摘录:
参见 手册中FORMAT块的最后一部分.
By default, date pads numeric fields with zeroes. 默认情况下date会在数字域上填充0
The following optional flags may follow '%': 下面这些可选的标识可以放在百分号后面:
- (hyphen) do not pad the field (连字符)不填充
_ (underscore) pad with spaces (下划线)用空格填充
0 (zero) pad with zeros (零)用0填充
另外,计算上一个整10分钟这里其实还有一个问题,就是跨天的问题:
假设当前时间是00:03,则用如上方法计算出的时间段是[23:50,00:00).
而我们希望的时间段是[23:50,24:00)
这里,还没有找到更好的方法,只能检测当 LAST_10MINUTE_END = "00:00" 时,替换为"24:00".
对应的日期如果用到,也要相应修改.
阅读(3744) | 评论(0) | 转发(0) |