正则匹配年月日时分秒
shell获取时间的相关命令
Linux shell获取时间和时间间隔(ms级别)
说明:在进⾏⼀些性能测试的时候,有时候我们希望能计算⼀个程序运⾏的时间,有时候可能会⾃⼰写⼀个shell脚本⽅便进⾏⼀些性能测试的控制(⽐如希望能运⾏N次取平均值等),总之,这其中有⼀个需求可能就是获取⼀个时间戳或时间差。
1. Linux shell获取时间的相关命令
time命令:获取⼀个程序的执⾏时间,可以获取到实际运⾏时间以及程序在⽤户态和内核态分别的时间,⼤部分的性能测试,可能只需要关注实际时间。
time命令的使⽤就很简单了,在原有的要运⾏的程序(可执⾏⽂件、脚本等任何可执⾏程序)之前加上time即可。
问题⼀:time命令的常⽤选项
使⽤time,常⽤的选项是:-f和-p。其中-f后⾯指定⼀个格式串,控制time的输出的格式,默认的time输出是real、user、sys三⾏以s的格式输出,通过-f可以控制。
-
p选项也是格式,表⽰使⽤posix标准的格式,主要的区别是显⽰的时间都是以s为单位的,具体关于格式的问题参考man time的帮助内容就知道了。
PS:-f选项没法⼯作?弄不清楚为何-f和-o等选项都⽆法⼯作,知道的请补充。(-p是⼯作的)
另⼀种控制格式的⽅法是设置TIMEFORMAT环境变量,具体参考man time可以知道这些格式控制符分别表⽰什么。举例如下:
[plain]view plaincopyprint?
#time pwd
/home/sgeng2
real    0m0.000s
user    0m0.000s
sys 0m0.000s
#export TIMEFORMAT="real time %E, user time %U,sys time %S"
#time pwd
/home/sgeng2
real time 0.000, user time 0.000,sys time 0.000
#time -p pwd
/home/sgeng2
real 0.00
user 0.00
sys 0.00
#
#time pwd
/home/sgeng2
real 0m0.000s
user 0m0.000s
sys 0m0.000s
#export TIMEFORMAT="real time %E, user time %U,sys time %S"
#time pwd
/home/sgeng2
real time 0.000, user time 0.000,sys time 0.000
#time -p pwd
/home/sgeng2
real 0.00
user 0.00
sys 0.00
#
PS:很奇怪,感觉time的有些格式和上⾯的选项⼀样,好像不完全⼯作,总之,关系不⼤,格式并不重要,⼀般使⽤-p以秒作为单位就⾜够了。
问题⼆:time命令的输出的问题
上⾯已经说到,好像-o选项并不⼯作,那么,我们就只能⾃⼰想办法了。有时候写脚本,就希望把time的结果输出到⽂件中,然后可能会根据time的输出进⾏⼀些处理,⽐如提取出real时间等。显然,⼤家能想到的是重定向了,⾄于重定向的使⽤这⾥显然不准备讨论(太复杂),只是提⽰⼀点:time命令的输出结果是输出到stderr的,不是stdout,所以进⾏重定向的时候要注意了。看懂下⾯的例⼦基本就能理解了:
[plain]view plaincopyprint?
#time pwd
/home/sgeng2
real    0m0.000s
user    0m0.000s
sys 0m0.000s
#time pwd >
real    0m0.000s
user    0m0.000s
sys 0m0.000s
#
/home/sgeng2
#time pwd 2>
/home/sgeng2
real    0m0.000s
user    0m0.000s
sys 0m0.000s
#
#(time pwd) 2>
/home/sgeng2
#
real    0m0.000s
user    0m0.000s
sys 0m0.000s
#(time pwd) >&
#
/
home/sgeng2
real    0m0.000s
user    0m0.000s
sys 0m0.000s
#
#time pwd
/home/sgeng2
real 0m0.000s
user 0m0.000s
sys 0m0.000s
#time pwd >
real 0m0.000s
user 0m0.000s
sys 0m0.000s
#
/home/sgeng2
#time pwd 2>
/home/sgeng2
real 0m0.000s
user 0m0.000s
sys 0m0.000s
#
#(time pwd) 2>
/home/sgeng2
#
real 0m0.000s
user 0m0.000s
sys 0m0.000s
#(time pwd) >&
#
/home/sgeng2
real 0m0.000s
user 0m0.000s
sys 0m0.000s
#
PS:这⾥更多的是涉及到的和重定向相关的内容,所以不会详细分析每⼀个例⼦。说明的是注意time pwd 2> 和(time pwd) 2> 的区别,前⾯⼀个的含义是把pwd的结果stderr重定向到,相当于"time (pwd 2> )"的结果。
date命令:
这⾥只说明⼀下⼏个常见的问题:
问题⼀:date的%s和%N
date中有很多控制格式的,其中%s是获取当前时间距离1970-01-01 00:00:00 UTC的时间差。date的其它很多格式控制都是控制当前时间的输出格式⽽已,⽐如只输出时分秒,只输出年⽉⽇等等,其中%N也是这⼀类,%N输出的是当前时间的纳秒部分,由于date并没有毫秒等级别的输出,所以在秒以下的内容都属于纳秒部分。所以从这个⾓度说,date是可以很精确的,可以达到纳秒级别。
问题⼆:获取⼀个时间戳
有时候会使⽤时间戳,或者随机数,UUID这样的东西,百度⼀下也有相关⽂章(⽐如搜索”shell date随机数“等)。⼀般来说,可以⽤%s 和%N组合的⽅式就没问题,同⼀秒内,两次运⾏%N肯定不会⼀样,所以%s和%N组合能得到⼀个唯⼀数。
[plain]view plaincopyprint?
#date +%s.%N
1337435374.969263560
#date +%s+%N
1337435377+310281496
#date +%s_%N
1337435381_209334510
#date +%s_%N
1337435383_169263078
#date +%s_%N
1337435383_830009679
#
PS:有时候可能希望⽤⼀个”唯⼀“的东西来对⽂件命名等,就可以加上时间戳了。
2. Linux shell获取时间差(使⽤date命令)
⾄于使⽤time命令,其本⾝就是获取⼀个时间差,但是显然,time只适⽤于⼀些简单的情况,因为后⾯的参数是可以执⾏的内容,有时候可能需要执⾏多条命令,⽤time就⽐较⿇烦。
(1) 秒为单位
date获取的是”当前时间“,显然,两次运⾏date就可以得到⼀个时间差,理论上,可以使⽤很多格式来表⽰date的输出,从⽽计算时间差,但是,显然,最直接的⽅式就是使⽤%s了,这样直接就可以计算出⼀个时间差,不需要那么复杂的shell字符串处理了。如下:
[plain]view plaincopyprint?
1. #start=$(date +%s) && sleep 2 && end=$(date +%s) && echo $(( $end - $start ))
2. 2
3. #start=$(date +%s) && sleep 3 && end=$(date +%s) && echo $(( $end - $start ))
4. 3
5. #
#start=$(date +%s) && sleep 2 && end=$(date +%s) && echo $(( $end - $start ))
2
#start=$(date +%s) && sleep 3 && end=$(date +%s) && echo $(( $end - $start ))
3
#
当然,这⾥是在terminal中测试的,所以⽤&&连续执⾏这些命令,对于脚本,⼀⾏⼀⾏的写就很好了。。。。
[plain]view plaincopyprint?
1. start=$(date +%s)
2. ...what to do
3. end=$(date +%s)
4. time=$(( $end - $start ))
5. echo $time
start=$(date +%s)
...what to do
end=$(date +%s)
time=$(( $end - $start ))
echo $time
(2) ms为单位
更多的性能测试等场合获取时间差,有可能希望精确到ms。事实上,使⽤date是可以达到ms的。直接上代码吧。
[plain]view plaincopyprint?
1. #! /bin/bash
2. #filename: test.sh
3.
4.
5. # arg1=start, arg2=end, format: %s.%N
6. function getTiming() {
7.    start=$1
8.    end=$2
9.
10.    start_s=$(echo $start | cut -d '.' -f 1)
11.    start_ns=$(echo $start | cut -d '.' -f 2)
12.    end_s=$(echo $end | cut -d '.' -f 1)
13.    end_ns=$(echo $end | cut -d '.' -f 2)
14.
15.
16. # for debug..
17. #    echo $start
18. #    echo $end
19.
20.
21.    time=$(( ( 10#$end_s - 10#$start_s ) * 1000 + ( 10#$end_ns / 1000000 - 10#$start_ns / 1000000 ) ))
22.
23.
24.    echo "$time ms"
25. }
26.
27.
28.
29.
30. echo "This is only a test to get a ms level "
31. start=$(date +%s.%N)
32. ls >& /dev/null    # hey, be quite, do not output
33. end=$(date +%s.%N)
34.
35.
36. getTiming $start $end
#! /bin/bash
#filename: test.sh
# arg1=start, arg2=end, format: %s.%N
function getTiming() {
start=$1
end=$2
start_s=$(echo $start | cut -d '.' -f 1)
start_ns=$(echo $start | cut -d '.' -f 2)
end_s=$(echo $end | cut -d '.' -f 1)
end_ns=$(echo $end | cut -d '.' -f 2)
# for debug..
#    echo $start
#    echo $end
time=$(( ( 10#$end_s - 10#$start_s ) * 1000 + ( 10#$end_ns / 1000000 - 10#$start_ns / 1000000 ) ))
echo "$time ms"
}
echo "This is only a test to get a ms level "
start=$(date +%s.%N)
ls >& /dev/null    # hey, be quite, do not output
end=$(date +%s.%N)
getTiming $start $end
PS:这个代码是⼀个简单的测试,可以获取到ls命令执⾏的时间,相信其执⾏时间已经够短了,如果你需要获取的时间差在ms以下,相信你不会使⽤shell了,嘿嘿,⾃然要靠C去弄了。
结果如下:
[html]view plaincopyprint?
1. #./test.sh
2. This is only a test to get a ms level
3. 3 ms

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。