我想做一个bash脚本,用于测量浏览器的启动时间,因为我正在使用html,它使用JavaScript获取了以毫秒为单位的时间戳加载时间。
在调用浏览器之前,在shell脚本中,我得到了时间戳:
date +%s
问题在于它以秒为单位获取时间戳,我需要以毫秒为单位,因为有时第二次运行时浏览器在不到一秒的时间内启动,因此我需要能够使用毫秒而不是秒来精确地测量该时间。
如何从bash脚本获取以毫秒为单位的时间戳?
我想做一个bash脚本,用于测量浏览器的启动时间,因为我正在使用html,它使用JavaScript获取了以毫秒为单位的时间戳加载时间。
在调用浏览器之前,在shell脚本中,我得到了时间戳:
date +%s
问题在于它以秒为单位获取时间戳,我需要以毫秒为单位,因为有时第二次运行时浏览器在不到一秒的时间内启动,因此我需要能够使用毫秒而不是秒来精确地测量该时间。
如何从bash脚本获取以毫秒为单位的时间戳?
Answers:
date +%s.%N
会给你,例如1364391019.877418748
。%N是当前秒过去的纳秒数。请注意,它是9位数字,并且默认情况下,日期小于100000000时,日期将用零填充。这实际上是一个问题,如果我们想对数字进行数学运算,因为bash会将前导零的数字视为八进制。可以通过在字段规范中使用连字符来禁用此填充,因此:
echo $((`date +%s`*1000+`date +%-N`/1000000))
从纪元开始会天真地给您毫秒。
但是,正如斯蒂芬·查泽拉斯(Stephane Chazelas)在下面的评论中指出的那样,这是两个不同的date
调用,将产生两个略有不同的时间。如果秒数在它们之间翻转,则计算将减少一整秒。所以:
echo $(($(date +'%s * 1000 + %-N / 1000000')))
或经过优化(感谢下面的评论,尽管这应该很明显):
echo $(( $(date '+%s%N') / 1000000));
$(($(date +'%s * 1000 + %N / 1000000')))
。那仍然没有多大意义,但是会更可靠。
%N
在BSD和OS X中不可用
echo $(( $(date '+%s%N') / 1000000))
呢?
使用GNU或ast-open实现date
(如果FEATURE_DATE_NANO
启用了该选项,则为astbox开放式实现),我将使用:
$ date +%s%3N
从Unix时代返回毫秒数。
%3N
是否需要进行必要的左零填充(无需阅读文档; ;-),可以这样做while sleep 0.05; do date +%s%3N; done
,是的,必要的零在其中。
%3N
确实是零填充。此外,我不认为您的解决方案会加零,只会延迟很小的响应时间。
%3N
确实填充了0。
如果有人使用以外的其他Shell bash
,ksh93
并且zsh
有一个浮点$SECONDS
变量(如果您这样做)typeset -F SECONDS
,则可以方便地准确地测量时间:
$ typeset -F SECONDS=0
$ do-something
something done
$ echo "$SECONDS seconds have elapsed"
18.3994340000 seconds have elapsed
由于版本4.3.13(2011)在模块中zsh
具有$EPOCHREALTIME
特殊的浮点变量zsh/datetime
:
$ zmodload zsh/datetime
$ echo $EPOCHREALTIME
1364401642.2725396156
$ printf '%d\n' $((EPOCHREALTIME*1000))
1364401755993
请注意,这是从返回的两个整数(秒和纳秒)得出的clock_gettime()
。在大多数系统上,这要比单个C double
浮点数所能容纳的精度更高,因此,在算术表达式中使用它时,精度会下降(1970年头几个月的日期除外)。
$ t=$EPOCHREALTIME
$ echo $t $((t))
1568473231.6078064442 1568473231.6078064
要计算高精度时差(尽管我怀疑您需要的精度超过毫秒),您可能需要使用$epochtime
特殊的数组(包含秒和纳秒作为两个单独的元素)。
从5.7(2018)版本开始,strftime
shell内置还支持%N
纳秒级格式àla GNU date
和a %.
来指定精度,因此也可以通过以下方式检索自纪元以来的毫秒数:
zmodload zsh/datetime
strftime %s%3. $epochtime
(或使用存储在变量中-s var
)
为了避免计算得出毫秒数,命令行JavaScript解释器可能会有所帮助:
bash-4.2$ node -e 'console.log(new Date().getTime())' # node.js
1364391220596
bash-4.2$ js60 -e 'print(new Date().getTime())' # SpiderMonkey
1364391220610
bash-4.2$ jsc -e 'print(new Date().getTime())' # WebKit
1364391220622
bash-4.2$ seed -e 'new Date().getTime()' # GNOME object bridge
1364391220669
在Ubuntu Eoan上包含那些解释器的软件包:
在bash 5+中,有一个微秒级的变量:$EPOCHREALTIME
。
所以:
$ echo "$(( ${EPOCHREALTIME//.} / 1000 ))"
1568385422635
从纪元(1/1/70)起以毫秒为单位打印时间。
如果失败,则必须使用日期。GNU日期:
echo "$(date +'%s%3N')"
https://serverfault.com/a/423642/465827中列出的替代方法之一
或brew install coreutils
对于OS X
或者,如果其他所有操作失败,则编译(gcc epochInµsec.c)此c程序(根据需要进行调整):
#include <stdio.h>
#include <sys/time.h>
int main(void)
{
struct timeval time_now;
gettimeofday(&time_now,NULL);
printf ("%ld secs, %ld usecs\n",time_now.tv_sec,time_now.tv_usec);
return 0;
}
请注意,调用任何外部程序都需要时间从磁盘读取和加载,启动,运行并最终打印输出。这将花费几毫秒。这是任何外部工具(包括日期)都可以达到的最低精度。