上一篇文章里,我谈到在 Linux 中至少有以下两种方法进行时间同步:

  1. Network Time Protocol daemon
  2. systemd-timesyncd

根据有关文档资料,第 1 种方法每隔 11 分钟同步一次。第 2 种方法是我推荐使用的,但它要多久同步一次呢?

使用 man systemd-timesyncd 命令查看相关文档:

从上述文档中可以看出,systemd-timesyncd 在每次时间同步后,都会更新 /var/lib/systemd/clock 文件。

$ ll /var/lib/systemd/clock
-rw-r--r-- 1 systemd-timesync systemd-timesync 0 10月 21 08:27 /var/lib/systemd/clock

嗯,上次时间同步是在 08:27,那么下次在什么时候同步呢?让我们写个 C# 程序来探查一下吧:

using System;
using System.IO;
using System.Threading;

sealed class TimesyncdMonitor
{
  static void Main()
  {
    var t0 = DateTime.MinValue;
    var watcher = new FileSystemWatcher("/var/lib/systemd", "clock");
    watcher.Changed += (_, e) => {
      var t1 = DateTime.Now; if (t0 == DateTime.MinValue) t0 = t1;
      Console.WriteLine("{0:dd HH:mm:ss}: {1,8:F3}",
        t1, (t1 - t0).TotalSeconds); t0 = t1; };
    watcher.EnableRaisingEvents = true;
    Thread.Sleep(Timeout.Infinite);
  }
}

简要说明:

  • FileSystemWatcher 类监视指定目录中特定文件的变化。
  • 当监视对象发生变化时,引发 Changed 事件。所以我们为该事件注册一个回调函数(lambda),显示本次事件发生时间以及与上次事件的间隔。
  • 设置 EnableRaisingEvents 属性为 true,开始进行监视。
  • 最后,调用 Thread 类的 Sleep 方法进入永久睡眠,等待事件发生。

注意,最后一条语句也可以用以下语句代替:

Console.ReadLine();

但是不要使用以下语句:

while (true) ;

这个程序的运行结果如下:

$ dmcs timesyncdmonitor.cs && mono timesyncdmonitor.exe

21 08:28:41:    0.000
21 08:30:49:  128.514
21 08:32:26:   96.449
21 08:32:58:   32.252
21 08:34:34:   96.499
21 08:38:29:  235.005
21 08:40:38:  128.252
21 08:44:54:  256.248
21 08:53:26:  512.251
21 09:10:30: 1024.251
21 09:44:39: 2048.245
21 10:18:47: 2048.249
21 10:52:55: 2048.250
21 11:27:03: 2048.250
21 12:01:12: 2048.255
21 12:35:20: 2048.298
21 13:09:28: 2048.245
21 13:43:36: 2048.210
21 14:17:45: 2048.249
21 14:51:53: 2048.249
21 15:26:01: 2048.252
21 16:00:09: 2048.261
21 16:34:18: 2048.239
21 17:08:26: 2048.250
^C

这样看来,systemd-timesyncd 应该是每隔 2048 秒(大约 34 分钟)同步一次。不过小数点后面的零头是什么意思?系统时钟与实际的物理时钟的误差?

哦,这个程序是我刚重启完电脑后立即运行的,前几行输出我猜应该是 systemd-timesyncd 在测试和选择合适的 NTP 服务器。

参考资料

  1. MSDN: FileSystemWatcher Class (System.IO)
  2. MSDN: Tread.Sleep Method (Int32) (System.Threading)