Linux中是否有一个shell命令来获取以毫秒为单位的时间?
15 回答
date +"%T.%N"
以纳秒返回当前时间。06:46:41.431857000
date +"%T.%6N"
返回当前时间,纳秒四舍五入到前 6 位,即微秒。06:47:07.183172
date +"%T.%3N"
返回当前时间,纳秒四舍五入到前 3 位,即毫秒。06:47:42.773
通常,date
命令格式的每个字段都可以指定一个可选的字段宽度。
date +%s%N
返回秒数 + 当前纳秒。
因此,echo $(($(date +%s%N)/1000000))
是您所需要的。
例子:
$ echo $(($(date +%s%N)/1000000))
1535546718115
date +%s
如果有用,则返回自纪元以来的秒数。
纳米是 10 -9和毫 10 -3。因此,我们可以使用纳秒的前三个字符来获取毫秒:
date +%s%3N
来自man date
:
%N 纳秒 (000000000..999999999)
自 1970 年 1 月 1 日 00:00:00 UTC 以来的 %s秒
资料来源:Server Fault 的如何在 Bash 中获取当前的 Unix 时间(以毫秒为单位)?.
在date
不支持该%N
标志的 OS X 上,我建议coreutils
使用Homebrew安装。这将使您可以访问一个名为的命令,该命令gdate
的行为与date
Linux 系统上的行为相同。
brew install coreutils
为了获得更“原生”的体验,您可以随时将其添加到您的.bash_aliases
:
alias date='gdate'
然后执行
$ date +%s%N
这是一个以毫秒为单位获取时间的 Linux 可移植 hack:
#!/bin/sh
read up rest </proc/uptime; t1="${up%.*}${up#*.}"
sleep 3 # your command
read up rest </proc/uptime; t2="${up%.*}${up#*.}"
millisec=$(( 10*(t2-t1) ))
echo $millisec
输出是:
3010
这是一个非常便宜的操作,它适用于 shell 内部和 procfs。
date
命令在 OS X 上没有提供毫秒,所以使用了 python 的别名
millis(){ python -c "import time; print(int(time.time()*1000))"; }
或者
alias millis='python -c "import time; print(int(time.time()*1000))"'
编辑:遵循@CharlesDuffy 的评论。分叉任何子进程需要额外的时间。
$ time date +%s%N
1597103627N
date +%s%N 0.00s user 0.00s system 63% cpu 0.006 total
Python 仍在改进它的 VM 启动时间,它的速度不如提前编译的代码(例如date
)。
在我的机器上,大约需要 30 毫秒 - 60 毫秒(即 6 毫秒的 5x-10 倍date
)
$ time python -c "import time; print(int(time.time()*1000))"
1597103899460
python -c "import time; print(int(time.time()*1000))" 0.03s user 0.01s system 83% cpu 0.053 total
我认为awk
比 轻量级python
,因此awk
在 6ms 到 12ms 的范围内(即日期的 1x 到 2x):
$ time awk '@load "time"; BEGIN{print int(1000 * gettimeofday())}'
1597103729525
awk '@load "time"; BEGIN{print int(1000 * gettimeofday())}' 0.00s user 0.00s system 74% cpu 0.010 total
在大多数情况下,其他答案可能就足够了,但当我在BusyBox系统上遇到问题时,我想我会加两分钱。
有问题的系统不支持%N
格式选项,也没有 Python 或 Perl 解释器。
经过多次挠头,我们(感谢戴夫!)想出了这个:
adjtimex | awk '/(time.tv_sec|time.tv_usec):/ { printf("%06d", $2) }'
adjtimex
它从(通常用于设置系统时钟的选项)的输出中提取秒和微秒,并在没有新行的情况下打印它们(因此它们粘在一起)。请注意,微秒字段必须预先填充零,但这不会影响超过六位数的秒字段。由此,将微秒转换为毫秒应该是微不足道的。
如果您需要一个尾随的新行(可能是因为它看起来更好),然后尝试
adjtimex | awk '/(time.tv_sec|time.tv_usec):/ { printf("%06d", $2) }' && printf "\n"
另请注意,这需要adjtimex
并且awk
可用。如果没有,那么使用 BusyBox,您可以使用以下命令在本地指向它们:
ln -s /bin/busybox ./adjtimex
ln -s /bin/busybox ./awk
然后将上述内容称为
./adjtimex | ./awk '/(time.tv_sec|time.tv_usec):/ { printf("%06d", $2) }'
或者当然你可以把它们放在你的PATH
编辑:
以上适用于我的 BusyBox 设备。在 Ubuntu 上我尝试了同样的事情并意识到它adjtimex
有不同的版本。在 Ubuntu 上,这可以输出以秒为单位的时间,小数点为微秒(包括尾随的新行)
sudo apt-get install adjtimex
adjtimex -p | awk '/raw time:/ { print $6 }'
不过,我不会在 Ubuntu 上这样做。我会用date +%s%N
纯 bash 解决方案
从bash
5.0(2019 年 1 月 7 日发布)开始,您可以使用包含自纪元以来的秒数的内置变量EPOCHREALTIME
,包括小数位到微秒 (μs) 精度(echo $EPOCHREALTIME
打印类似1547624774.371215
)。通过删除.
最后三个位置,我们得到毫秒:
要么使用
(( t = ${EPOCHREALTIME/./} / 1000 ))
或类似的东西
t=${EPOCHREALTIME/./}
t=${t%???}
无论哪种方式t
都会像1547624774371
.
显示带有时间和时区的日期
日期 +"%d-%m-%Y %T.%N %Z"
输出:22-04-2020 18:01:35.970289239 IST
我只是想在Alper 的回答中添加我必须做的事情才能使这些东西正常工作:
在 Mac 上,您需要brew install coreutils
.,所以我们可以使用gdate
. 否则在 Linux 上,它只是date
. 此功能将帮助您计时命令,而无需创建临时文件或任何东西:
function timeit() {
start=`gdate +%s%N`
bash -c $1
end=`gdate +%s%N`
runtime=$(((end-start)/1000000000.0))
echo " seconds"
}
您可以将其与字符串一起使用:
timeit 'tsc --noEmit'
像这样的 Python 脚本:
import time
cur_time = int(time.time()*1000)
当您从 4.1 版开始使用 GNU AWK 时,您可以加载时间库并执行以下操作:
$ awk '@load "time"; BEGIN{printf "%.6f", gettimeofday()}'
这将以亚秒精度打印自 1970-01-01T00:00:00 以来的当前时间(以秒为单位)。
the_time = gettimeofday()
返回自 1970-01-01 UTC 以来经过的时间(以秒为单位)作为浮点值。如果本平台时间不可用,则返回-1
并设置ERRNO
。返回的时间应该有亚秒精度,但实际精度可能因平台而异。如果标准 Cgettimeofday()
系统调用在该平台上可用,则它只返回值。否则,如果在 MS-Windows 上,它会尝试使用GetSystemTimeAsFileTime()
.来源:GNU awk 手册
在 Linux 系统上,标准 C 函数getimeofday()
以微秒精度返回时间。
我想从 bash 生成值并在 Java 代码中使用该值转换回日期(java.util)。
以下命令适用于我在 bash 文件中生成值:
date +%s000
Perl 可用于此目的,即使在 AIX 等特殊平台上也是如此。例子:
#!/usr/bin/perl -w
use strict;
use Time::HiRes qw(gettimeofday);
my ($t_sec, $usec) = gettimeofday ();
my $msec= int ($usec/1000);
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime ($t_sec);
printf "%04d-%02d-%02d %02d:%02d:%02d %03d\n",
1900+$year, 1+$mon, $mday, $hour, $min, $sec, $msec;
要打印小数秒:
start=$(($(date +%s%N)/1000000)) \
&& sleep 2 \
&& end=$(($(date +%s%N)/1000000)) \
&& runtime=$((end - start))
divisor=1000 \
&& foo=$(printf "%s.%s" $(( runtime / divisor )) $(( runtime % divisor ))) \
&& printf "runtime %s\n" $foo # in bash integer cannot cast to float
输出:runtime 2.3