Network Time Protocol时间同步协议,运行NTP服务的设备可以作为客户端从NTP服务器同步时间,也可以作为服务器供其他NTP客户端来同步时间。
时间同步 ntp
ntp是NTP的一种实现,ntpdate是ntp中的一个工具,也可以用来从外部时间服务器同步时间,但是会造成时间的突变,对于线上环境不是一个很理想的方式;ntp则采用平滑的方式,但是缺点是慢,而且对于超过17分钟的间隔会拒绝更新。
ntpdate和ntp服务都使用udp123端口,同一时间只能有一个在跑。所以通常的做法是开机时使用ntpdate进行一次时间校准,然后使用ntpd服务进行持续的对齐。当然也可以关掉ntpd服务,直接使用crontab每分钟执行一次ntpdate操作。
Linux中安装ntp,可以下载离线安装包:https://pkgs.org/download/ntp ,然后主要就是修改下配置文件:/etc/ntp.conf
ntp.conf
- driftfile /var/lib/ntp/drift
系统时间与BIOS时间的偏差记录,将自己主机的bios芯片震荡频率与上层的Time server频率比较,将误差记录在这个文件里
- restrict address [mask mask] [flag][…]
address地址参数可以是IP或者域名,mask是子网掩码(默认:address 0.0.0.0,mask 0.0.0.0),其中IP也可以是default,表示所有的IP
通常配置是先禁止所有的权限,然后再开放指定的权限,比如
1 2 3 4 5 6 7 8 9 10 11
| ## restrict default ignore ## restrict -6 default ignore restrict default nomodify notrap nopeer noquery restrict -6 default nomodify notrap nopeer noquery
## 开放本地环回接口所有权限 restrict 127.0.0.1 restrict ::1
## 允许192.168.1.0/24网段内主机进行时间同步 restrict 192.168.141.0 mask 255.255.255.0 nomodify notrap
|
fudge表示时间服务器的层次,stratum 0 表示为顶级;如果要向别的NTP服务器更新时间,请不要把它设为0
1 2 3
| ## 127.127.1.0表示以本机时间作为时间服务(内网服务一定要加上),prefer表示优先级最高 server 127.127.1.0 prefer fudge 127.127.1.0 stratum 0
|
示例
根据上面的描述,修改服务端/etc/ntp.conf如下,然后重启:systemctl restart ntp
1 2 3 4 5 6 7 8 9 10 11 12
| driftfile /var/lib/ntp/ntp.drift
server 127.127.1.0 prefer fudge 127.127.1.0 stratum 0
restrict -4 default kod notrap nomodify nopeer noquery limited restrict -6 default kod notrap nomodify nopeer noquery limited
restrict 127.0.0.1 restrict ::1
restrict 192.168.141.0 mask 255.255.255.0 nomodify notrap
|
通过netstat可以查看ntp服务的监听
1 2 3 4 5 6 7 8 9
| root@ubuntu:~# netstat -nulp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 192.168.141.13:123 0.0.0.0:* 4401/ntpd udp 0 0 127.0.0.1:123 0.0.0.0:* 4401/ntpd udp 0 0 0.0.0.0:123 0.0.0.0:* 4401/ntpd udp6 0 0 fe80::20c:29ff:fea2:123 :::* 4401/ntpd udp6 0 0 ::1:123 :::* 4401/ntpd udp6 0 0 :::123 :::* 4401/ntpd
|
对于客户端,只要改一下ntp服务的指向地址即可
如果觉得ntp同步时间太慢,可以关掉ntp,然后手动执行同步命令
也可以添加cron定时任务,每分钟执行一次
corntab -e1
| * * * * * /sbin/ntpdate 192.168.141.13
|
然后通过日志来查看定时任务执行情况
vim /var/log/cron1 2 3 4 5
| Nov 14 09:26:01 bogon CROND[2393]: (root) CMD (/sbin/ntpdate 192.168.141.13) Nov 14 09:27:01 bogon CROND[2474]: (root) CMD (/sbin/ntpdate 192.168.141.13) Nov 14 09:28:01 bogon CROND[2535]: (root) CMD (/sbin/ntpdate 192.168.141.13) Nov 14 09:29:01 bogon CROND[2598]: (root) CMD (/sbin/ntpdate 192.168.141.13) Nov 14 09:30:01 bogon CROND[2661]: (root) CMD (/sbin/ntpdate 192.168.141.13)
|
时间同步 chrony
chrony官网:https://chrony.tuxfamily.org
Chrony是NTP网络时间协议的另一种实现,与ntpd不同,它可以更快更准确地同步系统时钟,最大程度的减少时间和频率误差。ntpd的同步时间并不理想,有可能需要几小时来同步时间,而chrony只需要几分钟。并且chrony兼容ntp监听在udp123端口上,自己则监听在udp的323端口上。如果在chrony配置文件中指定了ntp服务器的地址,那么chrony就是一台客户端,会去同步ntp服务器的时间,如果在chrony配置了允许某些客户端来向自己同步时间,则chrony也充当了一台服务器。
vim /etc/chrony.conf1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| # 时间服务器,这里127.0.0.1表示自己 # ibust 会在chrony启动的2秒内,去快速poll服务器4次来矫正当前系统时间 # prefer 优先使用指定的服务器 # minpoll 最小轮询时间服务器的时间间隔,比如6是2的6次方,也就是64秒 # maxpoll 同上,比如10,表示最大轮询时间间隔是1024秒 server 127.0.0.1 iburst
# chronyd程序的主要行为之一,根据实际时间计算出计算机增减时间的比率,然后记录到一个文件中,在系统重启后为系统做出最佳时间补偿调整。 driftfile /var/lib/chrony/drift
# 一般如果系统时钟跟时间服务器不一致,chrony调整的方式是慢慢增加,或慢慢减少,不会一步到位,直接去跟时间服务器对齐 # makestep 1.0 3 表示如果时间服务器跟系统时间相差超过1秒,那么就在下3个时钟更新中追上时间服务器,这样能快速追平时间,但会带来时间跳跃。 makestep 1.0 3
# 表示将系统时钟同步到主板的硬件时钟去,缺省情况下是11分钟同步一次 rtcsync
# Enable hardware timestamping on all interfaces that support it. #hwtimestamp *
# Increase the minimum number of selectable sources required to adjust # the system clock. #minsources 2
# Allow NTP client access from local network. #allow 192.168.0.0/16
# Serve time even if not synchronized to a time source. #local stratum 10
# Specify file containing keys for NTP authentication. #keyfile /etc/chrony.keys
# Specify directory for log files. logdir /var/log/chrony
# Select which information is logged. #log measurements statistics tracking
|
可以通过chronyc命令来查看时间同步情况
1 2 3 4 5 6 7 8
| [root@bogon ~]# chronyc sources 210 Number of sources = 4 MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^- electrode.felixc.at 2 7 367 63 -2108us[-2493us] +/- 165ms ^- ntp6.flashdance.cx 2 7 377 8 -2077us[-2077us] +/- 85ms ^- ntp1.flashdance.cx 2 6 377 11 +1057us[+1057us] +/- 96ms ^* time.neu.edu.cn 1 6 377 13 -462us[ -896us] +/- 29ms
|
字段含义:
M:时钟源类型,^表示服务器,=表示二级时钟源,#表示本地连接的参考时钟
S:时钟源状态,*表示当前同步的源,+表示其他可接受的源,?表示连接丢失的源,x表示一个认为是falseticker时钟(即它的时间与大多数其他来源不一致),~表示其时间似乎具有太多可变性的来源
Name/IP address:时钟源地址
Stratum:时钟源层级,1表示本地连接的参考时钟,2表示通过第1层级计算机的时钟实现同步,依此类推。
Poll:时钟同步频率,以秒为单位,值是基数2的对数,不过chronyd会根据当时的情况自动改变轮询频率
Reach:时钟源的可达性的锁存值,当接收或丢失一次时进行一次更新,值377表示最后八次传输都收到了有效的回复
LastRx:从时钟源同步的最近一次时间,通常是几秒钟
Last sample:本地时间与时钟源的偏移量,方括号中的数字表示实际测量的偏移值,括号左侧表示原始测量值,这个值是经过调整以允许应用于本地时钟的任何偏差;括号右侧表示偏差值,+/-指示器后面的数字表示测量中的误差范围,+表示本地时钟快于时钟源
FAQ
date命令
1
| date "+%Y-%m-%d %H:%M:%S"
|
1 2 3 4
| ## 修改时间 date -s 11:12:00 ## 修改日期 date -s 07/13/2011
|
在/usr/share/zoneinfo/下面有很多时区文件,可以复制这些时区文件覆盖/etc/localtime,或修改链接/etc/locatime对应的文件
1 2 3
| cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
cron表达式
1
| {minute} {hour} {day-of-month} {month} {day-of-week} command
|
字段含义
1 2 3 4 5
| minute: 4个合法字符:,.*/ 取值范围:0~59 hour: 4个合法字符:,.*/ 取值范围:0~23 day-of-month:8个合法字符:,.*/?LWC 取值范围:0~31 month : 4个合法字符:,.*/ 取值范围:1~12,或JAN-DEC day-of-week: 8个合法字符:,.*/?LWC 取值范围:1~7,或SUN~SAT,1表示周日,2表示周一,以此类推
|
字符含义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| *:表示任意值,比如在{minute}域使用*, 就表示每分钟都会触发事件
?:只能在{day-of-month}和{day-of-week}两个域使用,也是匹配任意值,但实际不会。因为{day-of-month}和{day-of-week}会相互影响。 比如想在每月20日执行,不管20日到底是星期几,则表达式应该这样:13 13 15 20 * ? 其中最后一位只能用?,而不能使用*,如果使用*就表示不管星期几都会触发,但实际上并不想这样
-:表示范围,比如在{minute}域使用5-20,表示从5到20分钟每分钟触发一次
/:表示起始触发时间,然后每隔固定时间触发一次。比如在{minute}域使用5/20,表示第一次触发是在第5分钟,然后每20分钟触发一次,所以将在第25和45分别执行一次
,:表示枚举值,比如在{minute}域使用5,20,就表示在5和20分钟各触发一次
L:表示最后,只能在{day-of-month}和{day-of-week}两个域使用。如果在{day-of-week}域使用5L,就表示在最后一个星期四触发
W:表示有效工作日(周一到周五),只能在{day-of-month}域使用,系统将在离指定日期的最近的有效工作日触发事件。 例如:在{day-of-month}域使用5W, 如果5日是星期六,则将在最近的工作日,也就是星期五,4日触发。如果5日是星期天,则在6日(周一)触发; 如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。
LW:可以连用,表示在某个月最后一个工作日,即最后一个星期五
#:用于确定每个月第几个星期几,只能出现在{day-of-month}域,比如在4#2,表示某月的第二个星期三。
|
参考:
- https://www.zhaowenyu.com/ntp-doc/ntpd-conf.html
- https://blog.csdn.net/Victor2code/article/details/114091429
- https://rumenz.com/rumenbiji/linux-date-format.html
- https://www.mineor.xyz/posts/linux_cron/
- https://bajie.dev/posts/20211020-chrony/
- https://www.jianshu.com/p/303ff208f174