【问题标题】:Date command does not follow Linux specifications (Mac OS X Lion)日期命令不遵循 Linux 规范 (Mac OS X Lion)
【发布时间】:2012-04-05 23:48:54
【问题描述】:

我在我的 linux 机器上开发一个脚本已经有一段时间了,我也想在我的 Mac 上运行它。

我以为Mac上的功能和linux上的功能一样,但今天我意识到错了。我知道 Mac 上存在的函数较少,但我认为确实存在的函数具有相同的实现。

此问题与date 命令有关。

当我在我的 linux 机器上运行带有参数以提供以纳秒为单位的时间的命令时,我得到了正确的结果,但是当我在我的 mac 上运行它时,它没有该选项。

Linux-Machine> date +%N
55555555555 #Current time in nanoseconds
Mac-Machine> date +%N
N

如何在 Mac 上以 bash 命令的形式获取当前时间(以纳秒为单位)?

最坏的情况是我创建了一小段代码,用 C 或其他东西调用系统函数,然后在我的脚本中调用它。

非常感谢任何帮助!

【问题讨论】:

  • 最糟糕的是 sed ;-)
  • 我不会依赖 Linux 来遵守某些 Unix 标准。 Mac OS X 遵循单一 Unix 规范 V3,而不是 Linux。此外,从 bash 命令获得的具有纳秒精度的日期非常精确,但不是那么准确。你有什么需求?
  • 感谢您的意见。我将了解 GNU 与 BSD,并查看 sed 之间的差异。 @mouviciel,我想创建一个自定义 time 命令。
  • FWIW,带有zmodload zsh/datetime 的zsh 为您提供变量$EPOCHREALTIME 作为浮点纪元时间戳。当然如果你不使用 zsh 对你帮助不大,但一般来说,fork 一个进程来获得一个精确的时间值(通过使用date)只是值得怀疑的。是的,通过“保证”一个唯一的时间戳(与仅获取纪元秒数相比)可能会稍微好一些,但仅此而已

标签: macos bash date scripting porting


【解决方案1】:

这是因为 OSX 和 Linux 使用两组不同的工具。 Linux 使用 GNU 版本的 date 命令(因此是 GNU/Linux)。请记住,Linux 是 Linux,OS X 是 Unix。它们是不同的。

您可以安装 GNU date 命令,该命令包含在来自MacPorts 的“coreutils”包中。它将作为gdate 安装在您的系统上。您可以使用它,也可以将date 二进制文件与新的gdate 二进制文件链接;你的选择。

【讨论】:

  • 值得注意的是,coreutils 也在Homebrew 中,这使得安装变得轻而易举。只需安装 Homebrew,然后 brew install coreutils,你就有了 gdate。
  • 我知道这已经 2 岁多了,但谢谢!我在一个大型数据库项目中使用的脚本中有一个非常复杂的日期格式 sn-p,该项目利用了 date 的出色 -d 标志。很高兴仍然可以在 Mac 上使用它。
  • gdate +%H:%M:%S.%3N 将以毫秒为单位打印当前时间
【解决方案2】:

man date 表示不超过一秒。我建议尝试另一种语言(Python 2):

$ python -c 'import time; print repr(time.time())'
1332334298.898616

对于 Python 3,使用:

$ python -c 'import time; print(repr(time.time()))'

【讨论】:

  • 当我需要知道现在是多少纳秒时,我总是启动一个 Python 解释器。 ;-)
  • 哈哈,公平点 - 但你能想出更好的解决方案吗?
  • 感谢@Callum Macrae 的回答,但我想我必须选择另一个答案,因为它会给我更准确的结果。
  • 很公平。我不知道您没有分发脚本,在这种情况下您将无法使用 gdate。
  • 安装 coreutils 比打印纳秒更灵活;例如GNU date 强大的--date= 选项。
【解决方案3】:

有“Linux 规范”,但它们并没有过多地规范date 命令的行为。你所拥有的恰恰相反——Linux(或者更具体地说是 GNU 用户空间工具)有大量的扩展,它们在任何合理的定义下都与 Unix 不兼容。

有大量的标准规范这些事情。您应该查看的是POSIX,它需要

date [-u] [+format]

并没有更多的支持实现。 (您可能还想查看其他标准,例如 XPG 和 SUS,但至少,这些天您应该要求并期待 POSIX ......最后。)

POSIX 文档包含许多示例,但没有关于日期 conversion 的内容,但这是一个实际问题,许多脚本求助于date。此外,对于您的具体问题,在 POSIX 中没有任何以亚秒级精度报告时间。

无论如何,抱怨 *BSD 不是 Linux 在这里并没有什么帮助。您只需要了解差异是什么,并进行防御性编码。如果您的要求很复杂或不寻常,也许可以求助于 Perl 或 Python 之类的脚本语言,它们在标准安装中或多或少地执行这些类型的日期格式化操作(尽管 Perl 和 Python 都没有快速而优雅的方式来执行开箱即用地进行日期转换;解决方案往往会受到一些折磨)。

实际上,您可以比较MacOS date man pageLinux one 并尝试协调您的要求。

根据您的实际要求,MacOS date 不支持任何具有纳秒精度的格式字符串,但是当命令的执行需要大量纳秒时,您也不太可能收到该规模的有用结果。我会满足于毫秒级的精度(即使是最终数字中的执行时间也会被抛弃)并乘以得到纳秒级的数字。

nanoseconds () {
      python -c 'import time; print(int(time.time()*1000*1000*1000))'
}

(请注意 Python 3 的 print() 参数周围的括号。)您会注意到 Python 确实报告了纳秒精度的值(最后一位数字通常不是零),尽管通过您运行time.time() 的时间显然不再正确。

要了解错误率,

bash@macos-high-sierra$ python3
Python 3.5.1 (default, Dec 26 2015, 18:08:53)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> import timeit
>>> def nanoseconds ():
...   return int(time.time()*1000*1000*1000)
...
>>> timeit.timeit(nanoseconds, number=10000)
0.0066173350023746025
>>> timeit.timeit('int(time.time()*1000*1000*1000)', number=10000)
0.00557799199668807

启动 Python 和打印值的开销实际上可能会增加几个数量级的开销,但我没有尝试量化它。 (timeit 的输出以秒为单位。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 2011-10-11
    • 2011-10-09
    • 1970-01-01
    • 2011-12-29
    相关资源
    最近更新 更多