![如何获取自 Unix 纪元以来的毫秒数?](https://linux22.com/image/30406/%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E8%87%AA%20Unix%20%E7%BA%AA%E5%85%83%E4%BB%A5%E6%9D%A5%E7%9A%84%E6%AF%AB%E7%A7%92%E6%95%B0%EF%BC%9F.png)
我想做一个 bash 脚本来测量浏览器的启动时间,因为我使用的是 html,它使用 JavaScript 以毫秒为单位获取加载时间戳。
在调用浏览器之前的 shell 脚本中,我得到了时间戳:
date +%s
问题是它以秒为单位获取时间戳,而我需要以毫秒为单位,因为有时第二次运行时浏览器会在一秒内启动,我需要能够使用毫秒而不是秒来精确测量该时间。
如何从 bash 脚本获取时间戳(以毫秒为单位)?
答案1
使用 GNU 或 ast-open 实现date
(或 busybox',如果启用了该FEATURE_DATE_NANO
选项),我将使用:
$ date +%s%3N
返回自 Unix 纪元以来的毫秒数。
答案2
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));
答案3
如果有人使用除 之外的其他 shell bash
,ksh93
并且zsh
有一个浮点$SECONDS
变量,如果您执行 a 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()
。在大多数系统上,这比单个 Cdouble
浮点数所能容纳的精度更高,因此当您在算术表达式中使用它时,您将失去精度(1970 年头几个月的日期除外)。
$ t=$EPOCHREALTIME
$ echo $t $((t))
1568473231.6078064442 1568473231.6078064
要计算高精度时间差(尽管我怀疑您需要超过毫秒的精度),您可能需要使用$epochtime
特殊数组(其中包含秒和纳秒作为两个单独的元素)。
从版本 5.7 (2018) 开始,strftime
shell 内置还支持%N
GNU 的纳秒格式date
和%.
指定精度的 a ,因此也可以通过以下方式检索自纪元以来的毫秒数:
zmodload zsh/datetime
strftime %s%3. $epochtime
(或存储在变量中-s var
)
答案4
在 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;
}
请注意,调用任何外部程序都需要时间从磁盘读取和加载、启动、运行并最终打印输出。这将需要几毫秒。这是使用任何外部工具(包括日期)可以达到的最低精度。