在 Linux 上使用 NTP 保持精确的时间 | Linux 中国

如何保持正确的时间,如何使用 NTP 和 systemd 让你的计算机在不滥用时间服务器的前提下保持同步。

它的时间是多少?

让 Linux 来告诉你时间的时候,它是很奇怪的。你可能认为是使用 time 命令来告诉你时间,其实并不是,因为 time 只是一个测量一个进程运行了多少时间的计时器。为得到时间,你需要运行的是 date 命令,你想查看更多的日期,你可以运行 cal 命令。文件上的时间戳也是一个容易混淆的地方,因为根据你的发行版默认情况不同,它一般有两种不同的显示方法。下面是来自 Ubuntu 16.04 LTS 的示例:

$ ls -l
drwxrwxr-x 5 carla carla 4096 Mar 27 2017 stuff
drwxrwxr-x 2 carla carla 4096 Dec 8 11:32 things
-rw-rw-r-- 1 carla carla 626052 Nov 21 12:07 fatpdf.pdf
-rw-rw-r-- 1 carla carla 2781 Apr 18 2017 oddlots.txt

有些显示年,有些显示时间,这样的方式让你的文件更混乱。GNU 默认的情况是,如果你的文件在六个月以内,则显示时间而不是年。我想这样做可能是有原因的。如果你的 Linux 是这样的,尝试用 ls -l –time-style=long-iso 命令,让时间戳用同一种方式去显示,按字母顺序排序。请查阅 如何更改 Linux 的日期和时间:简单的命令[1] 去学习 Linux 上管理时间的各种方法。

检查当前设置

NTP —— 网络时间协议,它是保持计算机正确时间的老式方法。ntpd 是 NTP 守护程序,它通过周期性地查询公共时间服务器来按需调整你的计算机时间。它是一个简单的、轻量级的协议,使用它的基本功能时设置非常容易。systemd 通过使用 systemd-timesyncd.service 已经越俎代庖地 “干了 NTP 的活”,它可以用作 ntpd 的客户端。

在我们开始与 NTP “打交道” 之前,先花一些时间来了检查一下当前的时间设置是否正确。

你的系统上(至少)有两个时钟:系统时间 —— 它由 Linux 内核管理,第二个是你的主板上的硬件时钟,它也称为实时时钟(RTC)。当你进入系统的 BIOS 时,你可以看到你的硬件时钟的时间,你也可以去改变它的设置。当你安装一个新的 Linux 时,在一些图形化的时间管理器中,你会被询问是否设置你的 RTC 为 UTC(世界标准时间Coordinated Universal Time)时区,因为所有的时区和夏令时都是基于 UTC 的。你可以使用 hwclock 命令去检查:

$ sudo hwclock --debug
hwclock from util-linux 2.27.1
Using the /dev interface to the clock.
Hardware clock is on UTC time
Assuming hardware clock is kept in UTC time.
Waiting for clock tick...
...got clock tick
Time read from Hardware Clock: 2018/01/22 22:14:31
Hw clock time : 2018/01/22 22:14:31 = 1516659271 seconds since 1969
Time since last adjustment is 1516659271 seconds
Calculated Hardware Clock drift is 0.000000 seconds
Mon 22 Jan 2018 02:14:30 PM PST .202760 seconds

Hardware clock is on UTC time 表明了你的计算机的 RTC 是使用 UTC 时间的,虽然它把该时间转换为你的本地时间。如果它被设置为本地时间,它将显示 Hardware clock is on local time。

你应该有一个 /etc/adjtime 文件。如果没有的话,使用如下命令同步你的 RTC 为系统时间,

$ sudo hwclock -w

这个命令将生成该文件,内容看起来类似如下:

$ cat /etc/adjtime
0.000000 1516661953 0.000000
1516661953
UTC

新发明的 systemd 方式是去运行 timedatectl 命令,运行它不需要 root 权限:

$ timedatectl
 Local time: Mon 2018-01-22 14:17:51 PST
 Universal time: Mon 2018-01-22 22:17:51 UTC
 RTC time: Mon 2018-01-22 22:17:51
 Time zone: America/Los_Angeles (PST, -0800)
 Network time on: yes
NTP synchronized: yes
 RTC in local TZ: no

RTC in local TZ: no 表明它使用 UTC 时间。那么怎么改成使用本地时间?这里有许多种方法可以做到。最简单的方法是使用一个图形配置工具,比如像 openSUSE 中的 YaST。你也可使用 timedatectl:

$ timedatectl set-local-rtc 0

或者编辑 /etc/adjtime,将 UTC 替换为 LOCAL。

systemd-timesyncd 客户端

现在,我已经累了,但是我们刚到非常精彩的部分。谁能想到计时如此复杂?我们甚至还没有了解到它的皮毛;阅读 man 8 hwclock 去了解你的计算机如何保持时间的详细内容。

systemd 提供了 systemd-timesyncd.service 客户端,它可以查询远程时间服务器并调整你的本地系统时间。在 /etc/systemd/timesyncd.conf 中配置你的(时间)服务器。大多数 Linux 发行版都提供了一个默认配置,它指向他们维护的时间服务器上,比如,以下是 Fedora 的:

[Time]
#NTP=
#FallbackNTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org

你可以输入你希望使用的其它时间服务器,比如你自己的本地 NTP 服务器,在 NTP= 行上输入一个以空格分隔的服务器列表。(别忘了取消这一行的注释)NTP= 行上的任何内容都将覆盖掉 FallbackNTP 行上的配置项。

如果你不想使用 systemd 呢?那么,你将需要 NTP 就行。

配置 NTP 服务器和客户端

配置你自己的局域网 NTP 服务器是一个非常好的实践,这样你的网内计算机就不需要不停查询公共 NTP 服务器。在大多数 Linux 上的 NTP 都来自 ntp 包,它们大多都提供 /etc/ntp.conf 文件去配置时间服务器。查阅 NTP 时间服务器池[2] 去找到你所在的区域的合适的 NTP 服务器池。然后在你的 /etc/ntp.conf 中输入 4 – 5 个服务器,每个服务器用单独的一行:

driftfile /var/ntp.drift
logfile /var/log/ntp.log
server 0.europe.pool.ntp.org
server 1.europe.pool.ntp.org
server 2.europe.pool.ntp.org
server 3.europe.pool.ntp.org

driftfile 告诉 ntpd 它需要保存用于启动时使用时间服务器快速同步你的系统时钟的信息。而日志也将保存在他们自己指定的目录中,而不是转储到 syslog 中。如果你的 Linux 发行版默认提供了这些文件,请使用它们。

现在去启动守护程序;在大多数主流的 Linux 中它的命令是 sudo systemctl start ntpd。让它运行几分钟之后,我们再次去检查它的状态:

$ ntpq -p
 remote refid st t when poll reach delay offset jitter
==============================================================
+dev.smatwebdesi 192.168.194.89 3 u 25 64 37 92.456 -6.395 18.530
*chl.la 127.67.113.92 2 u 23 64 37 75.175 8.820 8.230
+four0.fairy.mat 35.73.197.144 2 u 22 64 37 116.272 -10.033 40.151
-195.21.152.161 195.66.241.2 2 u 27 64 37 107.559 1.822 27.346

我不知道这些内容是什么意思,但重要的是,你的守护程序已经与时间服务器开始对话了,而这正是我们所需要的。你可以去运行 sudo systemctl enable ntpd 命令,永久启用它。如果你的 Linux 没有使用 systemd,那么,给你留下的家庭作业就是找出如何去运行 ntpd。

现在,你可以在你的局域网中的其它计算机上设置 systemd-timesyncd,这样它们就可以使用你的本地 NTP 服务器了,或者,在它们上面安装 NTP,然后在它们的 /etc/ntp.conf 上输入你的本地 NTP 服务器。

NTP 服务器会受到攻击,而且需求在不断增加。你可以通过运行你自己的公共 NTP 服务器来提供帮助。下周我们将学习如何运行你自己的公共服务器。

CentOS 7.2 搭建内网ntp时间服务器

时间服务器说明

前面在系统的基础优化里说到了时间同步需要同步aliyun的时间,这样我们所有的服务器都需要到公网去同步时间,浪费很多网络资源,这里我们来搭建一下内网的时间服务器。

环境说明

1、时间服务器环境介绍

# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

# uname -r
3.10.0-327.el7.x86_64

# hostname -I
192.168.56.100 172.16.1.100

2、内网需要同步时间的服务器环境介绍

# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core) 

[root@linux-node2 ~]# uname -r
3.10.0-327.el7.x86_64

[root@linux-node2 ~]# hostname -I
192.168.56.12 172.16.1.12

yum安装ntp时间服务

# yum install -y ntp
# rpm -qa ntp        #下载后验证
ntp-4.2.6p5-25.el7.centos.2.x86_64

修改配置文件

[root@web01 ~]# grep -n "^[a-z]" /etc/ntp.conf    #过滤配置文件
4:driftfile /var/lib/ntp/drift       #默认的
9:restrict default nomodify      #注释掉地8行,添加这行,表示nomodify客户端可以同步时间。
14:restrict 127.0.0.1          #默认的
15:restrict ::1                     #默认的
26:server ntp1.aliyun.com       #添加时间源
27:server time.nist.gov            #添加时间源
39:includefile /etc/ntp/crypto/pw      #以下都是默认的
43:keys /etc/ntp/keys
61:disable monitor

启动时间服务器

# systemctl start ntpd
# netstat -lnuto|grep 123           #查看端口
udp        0      0 172.16.1.100:123        0.0.0.0:*                           off (0.00/0/0)
udp        0      0 192.168.56.100:123      0.0.0.0:*                           off (0.00/0/0)
udp        0      0 127.0.0.1:123           0.0.0.0:*                           off (0.00/0/0)
udp        0      0 0.0.0.0:123             0.0.0.0:*                           off (0.00/0/0)
udp6       0      0 fe80::20c:29ff:fe31:123 :::*                                off (0.00/0/0)
udp6       0      0 fe80::20c:29ff:fe31:123 :::*                                off (0.00/0/0)
udp6       0      0 ::1:123                 :::*                                off (0.00/0/0)
udp6       0      0 :::123                  :::*                                off (0.00/0/0)

启动后确认:

# ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 time5.aliyun.co 10.137.38.86     2 u   11   64    1    5.414   -0.946   0.000
 time-c-wwv.nist .STEP.          16 u    -   64    0    0.000    0.000   0.000
发现有两个可用的时间源

稍等几分钟后,在客户端同步时间

客户端如果有同步时间的定时任务需要取消掉。

1、到客户端查看当前时间

# date
Fri Jan 12 21:06:00 CST 2018

2、与时间服务器同步时间

# ntpdate -d 192.168.56.100
12 Jan 22:12:00 ntpdate[6677]: ntpdate [email protected] Wed Apr 12 21:24:06 UTC 2017 (1)
Looking for host 192.168.56.100 and service ntp
host found : linxu-node4
transmit(192.168.56.100)
receive(192.168.56.100)
transmit(192.168.56.100)
receive(192.168.56.100)
transmit(192.168.56.100)
receive(192.168.56.100)
transmit(192.168.56.100)
receive(192.168.56.100)
server 192.168.56.100, port 123
stratum 3, precision -24, leap 00, trust 000
refid [192.168.56.100], delay 0.02617, dispersion 0.00076
transmitted 4, in filter 4
reference time:    de02c1e5.530e0c26  Fri, Jan 12 2018 13:11:01.324
originate timestamp: de02c227.63d8db0f  Fri, Jan 12 2018 13:12:07.390
transmit timestamp:  de0340b6.c05f3381  Fri, Jan 12 2018 22:12:06.751
filter delay:  0.02617  0.02634  0.02634  0.02635 
         0.00000  0.00000  0.00000  0.00000 
filter offset: -32399.3 -32399.3 -32399.3 -32399.3
         0.000000 0.000000 0.000000 0.000000
delay 0.02617, dispersion 0.00076
offset -32399.360102

12 Jan 22:12:06 ntpdate[6677]: step time server 192.168.56.100 offset -32399.360102 sec

3、此时再查看客户端的时间

# date
Fri Jan 12 22:13:01 CST 2018

4、设置定时任务同步时间即可

# crontab -l
# tine rsync   time:2018/1/12
*/5 * * * * ntpdate 192.168.56.100 >/dev/null 2>&1

至此,内网的时间服务器就安装完成了,所有的内网服务器都可以到时间服务器来同步时间,不需要到公网上去同步时间了。

NTP时间服务器工作原理

NTP简介

NTP(Network Time Protocol, 网络时间协议)是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步,NTP基于UDP保温进行传输,使用UDP端口号为123。
使用NTP的目的是对网络内所有具有时钟的设备进行时钟同步,使网络内所有设备的时钟保持一致,从而使设备能够提供基于统一时间的多种应用。
对于运行NTP的本地系统,既可以接受来自其他时钟源的同步,又可以作为时钟源同步其他的时钟,并且可以喝其他设备互相同步。

NTP工作原理

NTP的基本工作原理如图1-1所示。Device A和Device B通过网络相连,他们都有自己独立的系统时钟,需要通过NTP实现各自系统时钟的自动同步。为便于理解,作如下假设:

  • 在Device A和Device B的系统时钟同步之前,DeviceA的时钟设定为10:00:00am,DeviceB的时钟设定为11:00:00am。
  • 设备B作为NTP时间服务器,即设备A将使自己的时钟与设备B的时钟同步。
  • NTP报文在设备A和设备B之间单向传输所需要的时间是1秒
  • FAQ

    图1-1 NTP原理图
    系统时钟同步过程如下:

  • 设备A发送一个NTP报文给设备B,该报文带有它离开设备A时的时间戳,该时间戳为10:00:00am(T1)。
  • 当此NTP报文到达设备B时,设备B加上自己的时间戳,该时间戳为11:00:01am(T2)。
  • 当此NTP报文离开设备B时,设备B再加上自己的时间戳,改时间戳为11:00:02(T3)。
  • 当设备A接收到该响应报文时,设备A的本地时间为10:00:03am(T4)。
  • 至此,设备A已经拥有足够的信息来计算两个重要的参数:
  • NTP报文的往返时延Delay=(T4-T1)-(T3-T2)=2 秒。
  • 设备A相对设备B的时间差offset=((T2-T1)+(T3-T4))/2=1小时。
  • 这样,设备A就能够根据这些信息来设定自己的时钟,使之与设备B的时钟同步。
    以上内容只是对NTP工作原理的一个粗略描述,更详细的资料可以参阅RFC 1305。

    NTP工作模式

    设备可以采用多种NTP工作模式进行时间同步:

  • 客户端/服务端模式
  • 对等体模式
  • 广播模式
  • 组播模式
  • 用户可以根据需要选择合适的工作模式。在不能确定服务器或对等体IP地址、网络中需要同步的设备很多等情况下,可以通过广播或组播模式实现时钟同步;服务器和对等体模式中,设备从指定的服务器或对等体获得时钟同步,增加了时钟的可靠性。
    1、客户端/服务器模式
    FAQ
    在该模式下,客户端能同步到服务器,而服务器无法同步到客户端。Mode3客户模式,mode4服务模式,
    适用于一台时间服务器接收上层时间服务器的时间信息,并提供时间信息给下层的用户。
    2、对等模式
    FAQ
    主动对等体和被动对等体可以互相同步。如果双方的时钟都已经同步,则以层数小的时钟为准。Mode1是主对等体模式,mode2被对等体模式,mode3客户模式,mode4是服务模式
    3、广播模式
    FAQ
    在广播模式中,服务器端周期性地向广播地址255.255.255.255发送时钟同步报文,报文中的Mode字段设置为5(广播模式)。客户端侦听来自服务器的广播报文。流程如图1-4所示。Mode3客户模式,mode4服务模式
    4、组播模式
    FAQ
    在组播模式中,服务端周期性地向组播地址发送时钟同步报文。报文中的mode5是组播模式,mode4是服务器模式,mode3是客户模式。