如何获取自 Unix 纪元以来的毫秒数?

如何获取自 Unix 纪元以来的毫秒数?

我想做一个 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 bashksh93并且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) 开始,strftimeshell 内置还支持%NGNU 的纳秒格式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;
}

请注意,调用任何外部程序都需要时间从磁盘读取和加载、启动、运行并最终打印输出。这将需要几毫秒。这是使用任何外部工具(包括日期)可以达到的最低精度。

相关内容