说明:在进行一些性能测试的时候,有时候我们希望能计算一个程序运行的时间,有时候可能会自己写一个shell脚本方便进行一些性能测试的控制(比如希望能运行N次取平均值等),总之,这其中有一个需求可能就是获取一个时间戳或时间差。
1. Linux shell获取时间的相关命令
time命令:获取一个程序的执行时间,可以获取到实际运行时间以及程序在用户态和内核态分别的时间,大部分的性能测试,可能只需要关注实际时间。
time命令的使用就很简单了,在原有的要运行的程序(可执行文件、脚本等任何可执行程序)之前加上time即可。
问题一:time命令的常用选项
使用time,常用的选项是:-f和-p。其中-f后面指定一个格式串,控制time的输出的格式,默认的time输出是real、user、sys三行以xmxxx.xxxs的格式输出,通过-f可以控制。
-p选项也是格式,表示使用posix标准的格式,主要的区别是显示的时间都是以s为单位的,具体关于格式的问题参考man time的帮助内容就知道了。
PS:-f选项没法工作?弄不清楚为何-f和-o等选项都无法工作,知道的请补充。(-p是工作的)
另一种控制格式的方法是设置TIMEFORMAT环境变量,具体参考man time可以知道这些格式控制符分别表示什么。举例如下:
- #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,所以进行重定向的时候要注意了。看懂下面的例子基本就能理解了:
- #time pwd
- /home/sgeng2
- real 0m0.000s
- user 0m0.000s
- sys 0m0.000s
- #time pwd > out.txt
- real 0m0.000s
- user 0m0.000s
- sys 0m0.000s
- #cat out.txt
- /home/sgeng2
- #time pwd 2> out.txt
- /home/sgeng2
- real 0m0.000s
- user 0m0.000s
- sys 0m0.000s
- #cat out.txt
- #(time pwd) 2> out.txt
- /home/sgeng2
- #cat out.txt
- real 0m0.000s
- user 0m0.000s
- sys 0m0.000s
- #(time pwd) >& out.txt
- #cat out.txt
- /home/sgeng2
- real 0m0.000s
- user 0m0.000s
- sys 0m0.000s
- #
PS:这里更多的是涉及到的和重定向相关的内容,所以不会详细分析每一个例子。说明的是注意time pwd 2> out.txt和(time pwd) 2> out.txt的区别,前面一个的含义是把pwd的结果stderr重定向到out.txt,相当于"time (pwd 2> out.txt)"的结果。
date命令:
关于date命令的使用,百度一把一大堆,就不重复了,例如可以参考:http://xingfujie.blog.51cto.com/2791569/637223
这里只说明一下几个常见的问题:
问题一: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组合能得到一个唯一数。
- #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字符串处理了。如下:
- #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中测试的,所以用&&连续执行这些命令,对于脚本,一行一行的写就很好了。。。。
- start=$(date +%s)
- ...what to do for timing...
- end=$(date +%s)
- time=$(( $end - $start ))
- echo $time
(2) ms为单位
更多的性能测试等场合获取时间差,有可能希望精确到ms。事实上,使用date是可以达到ms的。直接上代码吧。
- #! /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 time duration..."
- start=$(date +%s.%N)
- ls >& /dev/null # hey, be quite, do not output to console....
- end=$(date +%s.%N)
- getTiming $start $end
PS:这个代码是一个简单的测试,可以获取到ls命令执行的时间,相信其执行时间已经够短了,如果你需要获取的时间差在ms以下,相信你不会使用shell了,嘿嘿,自然要靠C去弄了。
结果如下:
- #./test.sh
- This is only a test to get a ms level time duration...
- 3 ms
- #./test.sh
- This is only a test to get a ms level time duration...
- 2 ms
- #./test.sh
- This is only a test to get a ms level time duration...
- 2 ms
- #
还满意吧,能获取到这么短的时间。当然,理论上可以获取到以ns为单位的时间差,但是,个人觉得用shell去弄这么小的时间差,你觉得准确么。。。
说明:
上面的代码的思路,其实很简单了,%s为距离标准时间的秒数,%N为当前时间的秒以下的部分,那么显然,%s和%N就表示了当前时间的完整时间戳,两个时间戳就差值就是时间差,问题就是如何处理的问题,大概就是:先使用%s.%N的格式获取到start和end时间,然后利用cut命令从start和end中获取到“.“前面的秒的部分和后面的纳秒的部分(说明:这里的在%s和%N之间插入点,只是作为分隔的作用,任何可能的字符都是可以的,只要能被cut分开就行);然后,用秒的部分相减,得到秒的差值,转换为毫秒的差值;然后,把纳秒的部分转换为毫秒之后求差值(可能为负数);最后,两个差值相加就是真正的以毫秒为单位的差值了。很容易理解,关键是cut的使用,对于shell高手来说,应该有很多方法可以对字符串提取,但是对于我这样的非shell高手,要自己用awk或sed什么的写一个提取的正则,还是很有难度,还好找到了cut命令,能很容易的对这种字符串进行提取。所以:这里的方法仅供参考。。。
关于代码中的“10#”,这是表示后面的数是10进制的数字,之所以需要这个是因为这里的纳秒的前面是以0开头的,shell中好像以0开头会默认认为是八进制,导致运行报错,总之,百度一下就找到了原因,这里就索性把所有的数字都加上了10#,表示都是10进制。
相关推荐
linux shell脚本获取时间判断时间差,进行计算,自动化
linux在shell中获取时间 linux在she
linux shell编程指南linux shell编程指南linux shell编程指南linux shell编程指南linux shell编程指南linux shell编程指南linux shell编程指南linux shell编程指南linux shell编程指南linux shell编程指南linux ...
LINUX SHELL命令练习 题
Linuxshell大作业.pdf
linux shell学习资料:Linux Shell从入门到精通、Linux Shell编程艺术、Linux Shell脚本攻略
linux C程序中获取shell脚本输出(如获取system命令输出)
linux 获取cpu shelllinux 获取cpu shelllinux 获取cpu shelllinux 获取cpu shell
Linux Shell Scripting Cookbook(3rd) 英文mobi 第3版 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
linux shell 视频教学 轻松学习shell
Linux Shell脚本手册 - 第三版,. This book will take you through useful real-world recipes designed to make your daily life easier when working with the shell.
Linux Shell实例精讲,大量实例shell,容易理解和实践
LinuxShell脚本编程实例.pdf
Linux Shell常用技巧Linux Shell常用技巧
通过linux的SSH端口使用java代码远程对指定的linux服务器上执行shell命令,实测有用
linux shell 应用.chm,学习linux shell资料
LinuxShell.pdf LinuxShell.pdf LinuxShell.pdf
linux shell 编程电子书,学习linux shell很不错的资料,高清的
主要介绍了linux shell实现求一个多维数组中的最大和最小值,需要的朋友可以参考下
linux_shell编程入门书籍,配合实例讲解,有助于新手入门,欢迎下载