如果系统设置的日期超过 2038 年,则 ntpdate 失败

如果系统设置的日期超过 2038 年,则 ntpdate 失败

当前正确的日期是 2016 年 CST 25 月 25 日星期五 12:11:07。

当我将日期更改为“2018/01/01”时,ntpdate 工作正常。

当我将日期更改为“2099/01/01",ntpdate 无法正常工作。

好的:

[root@oldboylinux ~]# date -s "2018/01/01"
Mon Jan  1 00:00:00 CST 2018

[root@oldboylinux ~]# /usr/sbin/ntpdate time.nist.gov
25 Mar 12:06:22 ntpdate[7187]: step time server 216.229.0.179 offset -55857225.378947 sec

不好:

[root@oldboylinux ~]#date -s "2099/01/01"
Thu Jan  1 00:00:00 CST 2099

[root@oldboylinux ~]# /usr/sbin/ntpdate time.nist.gov
 1 May 18:36:59 ntpdate[7189]: step time server 216.229.0.179 offset 1682966210.024232 sec

5 月 1 日星期一 18:41:18 CST 2152 是错误的日期。

ntpdate有有效范围吗?

答案1

首先一些注意事项:

  • 当前版本的 NTP (v4)使用eras进行操作。

  • 一个纪元为 136 年(以无符号 32 位整数表示的秒数)。或者大致

      60 * 60 * 24 * 365 * 136 = 4288896000 
                          2^32 = 4294967296
    
      4294967296 − 4288896000 = 6071296
       6071296 / 60 / 60 ∕ 24 ≈ 70 (days, not accounting for leaps)
    
  • 0时代:黄金时期,或基准日期“0时代”,是 UTC 时间 1900 年 1 月 1 日 00:00。

  • 时代1:从 2036 年初的某个时间开始。(UNIX-2038 之前的两年)

  • 时代2:故事开始于 2172 年初的某个时间。

  • 等等(对于其他一些例子,请查看RFC 5905 第 14 页.)

  • ntpdate使用 64 位的 NTP 时间戳。秒为 32 位,分数为 32 位。

  • 也许有点令人困惑; NTP-date 使用 128 位并包含纪元。这跨越了宇宙的年龄并延伸到遥远的未来。

如中所述NTP部分的 ”2038 年问题“-维基百科页面你有一个绝对限制68岁两个 NTP 时间戳之间。 ( 136 / 2 = 68)。不过,为了消除歧义,应该使用更窄的频带。

NTP 时间戳参考相对时间而非绝对时间进行操作;服务器通过与其自身时间的相对偏移量向客户端提供更正。即:它没有说:

— 日期是 2016 年 3 月 26 日

而是(简化为 NTP 的工作原理):

— 你落后了 +123412512.918 秒, 或者:
— 你落后了 -2652221.3466 秒, ETC。

或者引用 RFC 中的内容:

时间戳是无符号值,对它们的操作会产生相同或相邻时代的结果。纪元 0 包括从主要纪元到 2036 年某个时间的日期,此时时间戳字段环绕并建立纪元 1 的基准日期。

就你的情况而言,当你的年份是 2099 年时,你已经是未来 68 年以上的人了——大约 15 年。你最终来到了 2152 年,我们得到的是:

 2152 - 2016 = 136 (One era)

或者换一种说法:

                    2099 - 2036 = 63          (years into era 1)
        63 * 365 * 24 * 60 * 60 = 1986768000  (approx NTP time stamp for 2099)
       116 * 365 * 24 * 60 * 60 = 3658176000  (approx NTP time stamp for 2016)
       3658176000 - 1986768000  = 1671408000  (approx diff)
1671408000 / 60 / 60 / 24 / 365 = 53          (approx years)

1986768000 < 3658176000 thus add 1671408000

2099 + 53 = 2152 (the year your system was corrected to)

所以,是的,回答你的问题:

——ntpdate有有效射程吗?

是的。 ± 68 年,尽管最大有效射程有点窄。

NTP本身是无限的。

看一下RFC 5905如果有兴趣。另请注意,过时的 RFC 可能包含有趣的信息,例如附录 E. NTP 时间刻度及其计时法 在 RFC 1305 中


(附: 与 UNIX 时间戳相比,1970 + 68 = 2038.)

答案2

您看到的是常见的“bug”,称为 2038 年问题,又名 Y2K38 bug,它仍然存在于 32 位 Linux 服务器中。

到 2000 年左右,我们意识到除了 2000 年/千年错误之外,未来还会出现另一个与时间相关的错误。 (是的,我是千年虫“预防”团队的一员)

由于 Unix 纪元是一个 32 位秒计数器,始于 1970 年 1 月 1 日,并且只是一个有符号的 32 位整数,因此它的上限为 03:14:07(并且在某些系统中仍然如此)世界标准时间 2038 年 1 月 19 日。https://en.wikipedia.org/wiki/Year_2038_problem

在最新的实现中,它已扩展至 64 位。

从 NetBSD 版本 6.0(2012 年 10 月发布)开始,NetBSD 操作系统对 32 位和 64 位架构均使用 64 位 time_t。为具有 32 位 time_t 的较旧 NetBSD 版本编译的应用程序通过二进制兼容层得到支持,但此类较旧的应用程序仍将受到 2038 年问题的影响。 [13]

OpenBSD 自 2014 年 5 月发布的 5.5 版本开始,也对 32 位和 64 位架构使用 64 位 time_t。与 NetBSD 相比,它没有二进制兼容层。因此,期望 32 位 time_t 的应用程序和使用与 time_t 不同的任何内容来存储时间值的应用程序可能会崩溃。 [14]

Linux 仅对 64 位架构使用 64 位 time_t;由于向后兼容性,纯 32 位 ABI 不会改变。[15]目前正在进行的工作主要针对嵌入式 Linux 系统,以在 32 位架构上支持 64 位 time_t

作为一个民间传说历史和一个相当精心设计的骗局,约翰·蒂托(John Titor)因 2038 年错误而被送回过去获取大型机以帮助纠正未来的遗留问题,并在 2038 年预测希拉里·克林顿(Hillary Clinton)统治下的美国内战/核战争。我们的平行现实。

http://www.strangerdimensions.com/2011/10/03/john-titor-the-ibm-5100/

约翰·蒂托 (John Titor) 的故事始于 2036 年。蒂托 (Titor) 属于一个由七人组成的团队,被选中踏上穿越时空之旅。他在一个被自私、愤世嫉俗和腐败政府摧毁、被核战争蹂躏的世界里经历了难以想象的恐怖。更糟糕的是,他们仅存的技术在 2038 年受到了迫在眉睫的 UNIX 超时错误的威胁。

请同时参阅https://en.wikipedia.org/wiki/9223372036854775807

采用 32 位类型的系统很容易受到 2038 年问题的影响,因此许多实现已转向更广泛的 64 位类型,最大值为 263−1 对应于从现在起 2920 亿年的时间点。

那么回到你的 ntpdate 问题。

关于2038的极限。所以问题是 time_t 是一个 32 位有符号整数。即一个 32 位整数,最后一位专用于信号。因此,实际上您只能存储数字(然后是 -0x7fffffff 和 +7fffffff 之间的秒数(+2147483647)。因此 +2147483647 将时间间隔的表示限制为 1970 年 1 月 1 日+2147483647 秒,这意味着 ntpdate 仅是能够在您的系统中存储截至 2038 年 1 月 19 日 03:14:07 UTC 的日期。

关于 2038 年之后的日期,问题在于将字符串转换为内部表示形式(time_t/32 位整数)的代码例程会回绕或简单地重置为日/0 秒,具体取决于库实现。

关于你的上限年份。系统中的 time_t 是一个有符号整数,因此库将上限检查为无符号整数的值,在 1970 年 1 月 1 日之后的 +4294967295 秒处,它将在 2106 年左右的某个地方给出上限。取决于实现,检查实际上可能更多地在字符串中完成,或者行为是由于 32 位整数的属性,仅检查 ntpdate 代码。

INT_MAX(32 位)= 2147483647
UINT_MAX(32 位)= 4294967295 (0xffffffff)

https://en.wikipedia.org/wiki/Year_2038_problem

例如,将 time_t 更改为无符号 32 位整数,这会将范围扩展到 2106 年,会对存储、检索或操作 1970 年之前的日期的程序产生不利影响,因为此类日期由负数表示

作为最后一个脚注,请注意系统可能在系统/操作系统代码和 RTC 时钟中缺乏 y2k38 合规性。

在操作系统级别,使用 64 位 Linux(如果架构允许)现在就可以修复它,或者希望 32 位 Linux 在不久的将来能够修复它。

至于旧机器中的 RTC,这意味着您将在 2038 年之后收到数据乱码,至少在日志中,直到 ntpd 启动并更正系统日期为止。

相关内容