ARM40-A5应用——与网络时间的同步1(概述)
2018.6.28
版权声明:本文为博主原创文章,允许转载。
本文介绍ARM40-A5本地系统时间、硬件时间、时区、网络时间、ntpdate、ntpd、rdate等概念。
在《ARM40-A5应用——与网络时间的同步2(内核默认方式)》中,介绍Linux内核默认的时间设置方式;
在《ARM40-A5应用——与网络时间的同步3(发行版方式)》中,介绍大部分发行版使用的时间设置方式。
一、8025T 时钟芯片简介
ARM40-A5采用8025T 给主板提供本地实时时钟。8025T实时时钟芯片具有极低的功耗,内置高稳定度的32.768kHz的晶体,并自带温度补偿功能。在电表、水表、燃气表,工业控制,门禁,安防等领域得到广泛的应用。
二、Linux时钟简介
Linux时钟可分为系统时钟(System Clock)和硬件时钟(Real Time Clock,简称RTC)。系统时钟是指当前Linux Kernel中的时钟,而硬件时钟则是主板上由电池供电的时钟。当Linux启动时,系统时钟会去读取硬件时钟的设置,然后系统时钟就会独立于硬件时钟运作。用于时钟查看和设置的命令主要有date、hwclock。
系统启动和关闭时,硬件时钟与系统时钟之间的同步有两种方式(以中国为例,用CST代表本地时间):
方式A(内核方式,Linux内核默认的方式): 硬件时钟为UTC(世界标准时间,协调世界时),系统时钟为CST
开机: RTC --> UTC(RTC中存放UTC时间)–> 读取时区 --> 系统时钟为CST
更新时间: 系统时钟为CST --> 将UTC时间存入RTC
这种方式下,例如,date得到系统时间为19:00,则hwclock得到的时间为11:00.
方式B(发行版方式、Windows方式,大部分发行版使用这种方式):硬件时钟为CST,系统时钟也为CST
开机: RTC --> CST(将硬件时钟看成是CST时间)
更新时间: CST --存储到–> RTC
这种方式下,例如,date得到系统时间为19:00,则hwclock得到的时间为19:00.
在本文中,我们介绍方式A,方式B在《ARM40-A5应用——与网络时间的同步(2)》中介绍。
三、时区
(1)显示系统的日期与时间
root@ARM40:~# date // 显示系统的日期与时间,默认显示UTC时间
Thu Jun 28 01:01:31 UTC 2018
date命令默认是显示UTC时间。UTC为0时区的时间,即协调世界时(Universal Time Coordinated)。对应的,北京的时区为东八区,即CST 时间(或CST-8时间)。北京为早上八点(东八区)时,UTC时间为零点,时间比北京时间晚八小时。
root@ARM40:~# date -R // 显示时区
Wed, 12 Sep 2018 17:42:59 +0800 //东八区
(2)显示北京时间
如果要显示北京时间呢?命令如下:
root@ARM40:/etc/ppp# TZ=CST-8 date // 仅本次,显示CST-8时区的系统日期与时间
Thu Jun 28 09:01:33 CST 2018 // 可见,北京时间比UTC时间早8小时
(3)默认即显示北京时间
如果我们希望date命令默认不是显示UTC时间,而是默认显示CST-8时间呢?
在/etc/profile 中增加:
export TZ='CST-8'
修改后,我们测试一下看看:
root@ARM40:~# source /etc/profile
root@ARM40:~# date
Thu Jun 28 09:19:20 CST 2018 // 可见,date命令已默认显示北京时间
在date命令默认显示北京时间的情况下,如果我们想看看UTC时间呢?
root@ARM40:~# date -u
Thu Jun 28 01:19:22 UTC 2018
四、CMOS时间
(1)显示CMOS时间
ARM40-A5采用8025T 给主板提供本地实时时钟,其概念类似于电脑上的CMOS时间。8025T中默认应存储UTC时间。
root@ARM40:~# date -u
Thu Jun 28 01:55:14 UTC 2018
root@ARM40:~# hwclock // 显示8025T存储的时间,hwclock显示的是UTC时间
Thu Jun 28 01:55:14 2018 0.000000 seconds
上面的两行测试,也可能因为8025T保存的时间原本就不准确,而出现date时间与hwclock时间不一致的情况。此时需要校准8025T中的时间。
(2)校准CMOS时间
如果8025T保存的时间不够准确,则需要校时,命令如下:
root@ARM40:~# export TZ=CST-8 // 临时设置为CST-8 时区
root@ARM40:~# date 062513272018.00 // 设置为 2018-06-25-13:27:00,若设置距离当前时间较远的时间,系统可能会拒绝
Mon Jun 25 13:27:00 CST 2018
root@ARM40:~# date -u // 以UTC时区显示系统的日期与时间
Mon Jun 25 05:27:00 UTC 2018
root@ARM40:~# hwclock -w --utc // 将date时间对应的UTC时间存入8025T中
root@ARM40:~# hwclock // 显示8025T存储的时间,hwclock显示的是UTC时间
Mon Jun 25 05:27:12 2018 0.000000 seconds
测试:
在8025T的电池存在的情况下,给ARM40-A5断电,过几分钟后,再次上电。
因为上电时会运行 /etc/profile 中的 export TZ=‘CST-8’ 的,所以上电后date默认显示的是CST-8 时间。
root@ARM40:~# date // 显示系统的日期与时间,此时默认显示CST-8时间
Mon Jun 25 21:33:10 CST 2018 // 对应的UTC时间为 Jun 25 13:33:10
root@ARM40:~# date -u
Mon Jun 25 13:33:12 UTC 2018
root@ARM40:~# hwclock // 显示8025T存储的时间,hwclock显示的是UTC时间
Mon Jun 25 13:33:20 2018 0.000000 seconds
五、使用ntpdate与网络时间同步
为了避免主机时间因为长期运作下所导致的时间偏差,进行时间同步(synchronize)的工作是非常必要的。
(1)从时间服务器获取网络时间并同步
例1:(ARM40-A5位于内网的情况)
killall ntpd // ntpd与ntpdate冲突,需要kill掉
ifconfig eth0 192.168.1.5 // 这个例子是内网的情况
route add default gw 192.168.1.1
ntpdate 120.25.108.11 // 时间服务器1,阿里云提供
ntpdate 182.92.12.11 // 时间服务器2,阿里云提供
ntpdate cn.pool.ntp.org // 时间服务器3,需要DNS
例2:(ARM40-A5使用4G、GPRS联网的情况)
《ARM40-A5应用——GPRS模块ppp拨号上网》
《ARM40-A5应用——4G模块EC20-CE拨号上网》
killall ntpd // ntpd与ntpdate冲突,需要kill掉
ntpdate 120.25.108.11 // 时间服务器1,阿里云提供
// 28 Jun 11:15:44 ntpdate[22335]: adjust time server 120.25.108.11 offset 0.289128 sec
ntpdate 182.92.12.11 // 时间服务器2,阿里云提供
// 28 Jun 11:16:15 ntpdate[22353]: adjust time server 182.92.12.11 offset 0.234394 sec
ntpdate cn.pool.ntp.org // 时间服务器3,需要DNS
// 28 Jun 11:15:05 ntpdate[22321]: step time server 85.199.214.101 offset 247081.637253 sec
时间同步完毕后,用 date 命令观察显示的时间是否与手机上此刻的时间相同,相同则表示同步成功:
root@ARM40:~# date
Thu Jun 28 11:25:18 CST 2018
(2)定期与网络时间同步
一般配合crontab 命令,来进行定期同步设置。比如,在 crontab -e 中添加:
root@ARM40:~# crontab -e // 编辑 crontab 的内容:定期与网络时间同步
*/30 * * * * (ntpdate 120.25.108.11) && (hwclock -w --utc) >/dev/null 2>&1
这样,每30分钟,同步一次时间。ntp服务器为120.25.108.11。其中的 hwclock -w --utc 是更新后把时间写入CMOS。
root@ARM40:/# crontab -l // 查看 crontab 的内容
*/30 * * * * (ntpdate 120.25.108.11) && (hwclock -w --utc) >/dev/null 2>&1
在开发和测试阶段,每30分钟同步一次时间,这样测试需要等太久,下面提供两个测试用例。
① 首先查看ps,kill 掉 crond 和之前的crontab工作排程。
② 修改 crontab -e 的内容后,重新crond。
下面是修改 crontab -e 内容的示例:
root@ARM40:~# crontab -e // 编辑 crontab 的内容:测试每1分钟同步一次
* * * * * * (ntpdate 120.25.108.11) && (hwclock -w --utc) >/dev/null 2>&1
root@ARM40:/# crontab -e // 编辑 crontab 的内容:测试每1分钟给 /dev/ttyS0 发一个字符串
* * * * * echo "Good morning" >> /dev/ttyS0
注意:利用crond服务实现NTP定时同步可能出现的问题
(1)crontab -e 时可能会出现下面的提示:
crontab: can't change directory to '/var/spool/cron/crontabs': No such file or directory
此时需要建立相应的文件:
root@ARM40:~# mkdir -p /var/spool/cron/crontabs
(2)crontab -e 设置好同步时间后,需要打开 crond 服务:
root@ARM40:~# crond
ps 可以看到 crond 服务已开启。
(3)上电自启动crontab排程
如果要每次开机启动后都会自动运行这些工作,则
① 建立 /etc/cron.arm40 文件,内容为:
*/30 * * * * (ntpdate 120.25.108.11) && (hwclock -w --utc) >/dev/null 2>&1
② 在 /etc/profile 文件中加上:
killall ntpd
mkdir -p /var/spool/cron/crontabs
crontab /etc/cron.arm40
crond
这样,每次开机启动后都会开启排程,并且在每30分钟都会同步一次时间。
六、使用ntpd与网络时间同步
使用ntpd服务,要好于ntpdate加crontab的组合。因为,ntpdate同步时间,会造成时间的跳跃,对一些依赖时间的程序和服务会造成影响。比如sleep,timer等。而且,ntpd服务可以在修正时间的同时,修正cpu tick。理想的做法为,在开机的时候,使用ntpdate强制同步时间,在其他时候使用ntpd服务来同步时间。
要注意的是,ntpd 有一个自我保护设置:如果本机与上源时间相差太大,ntpd 不运行。所以新设置的时间服务器一定要先 ntpdate 从上源取得时间初值,然后启动 ntpd 服务。ntpd服务运行后,先是每64秒与上源服务器同步一次,根据每次同步时测得的误差值经复杂计算逐步调整自己的时间,随着误差减小,逐步增加同步的间隔。每次跳动,都会重复这个调整的过程。
root@ARM40:~# /etc/init.d/S49ntp restart
Restarting ntpd:
Stopping ntpd: FAIL
Starting ntpd: OK
查看端口:
root@ARM40:~# netstat -ln | grep 123
使用 ntpq -p 查询网络中的NTP服务器,同时显示客户端和每个服务器的关系。在这之前,可能需要设置DNS。
echo "nameserver 223.5.5.5" > /etc/resolv.conf
echo "nameserver 223.6.6.6" >> /etc/resolv.conf
然后 ntpq -p 查询NTP服务器,当然,不查询也没任何问题。
七、使用rdate与网络时间同步
(1)使用rdate与网络时间同步
由于ntp协议容易受到攻击,很多机房都限制了该协议,或者直接封掉123端口,可以使用rdate命令来同步时间。rdate 使用tcp协议,端口37。
rdate命令用于显示其他主机的日期与时间。执行rdate指令,向其它主机询问系统时间并显示出来。
语法
rdate [-ps][主机名称或IP地址…]
参数:
-p 显示远端主机的日期与时间。
-s 把从远端主机收到的日期和时间,回存到本地主机的系统时间。
实作如下:
root@ARM40:/etc# rdate -p time.nist.gov
Thu Jun 28 10:47:03 2018 // 显示的是UTC时间
root@ARM40:/etc# export TZ=CST-8
root@ARM40:/etc# rdate -p time.nist.gov
Thu Jun 28 18:47:27 2018 // 显示的是CST-8时间
root@ARM40:/etc# rdate -p 129.6.15.28
Thu Jun 28 19:01:12 2018
root@ARM40:/etc# rdate -s 129.6.15.28
root@ARM40:/etc# date
Thu Jun 28 19:01:15 2018
root@ARM40:/etc# rdate -s time-b.nist.gov
root@ARM40:/etc# date
Thu Jun 28 18:47:30 2018 // 显示的是CST-8时间
(2)部署一套自己的 rdate 时间服务器
在Linux服务器上启动时钟服务
#chkconfig time on
如果不启动这个服务,在client运行rdate同步时间时会报错的:
rdate: couldn’t connect to host 192.168.2.31: Connection refused
八、例子
见《ARM40-A5应用——与网络时间的同步2(内核默认方式)》《ARM40-A5应用——与网络时间的同步3(发行版方式)》
九、常见问题
(1)时间服务器
在NTP官方网站可找到提供同步服务的NTP SERVER,当然也可以自己搭建NTP服务器。
NTP官网地址: http://www.pool.ntp.org/en/
(2)rdate时间服务器
更多的rdate时间服务器见 https://tf.nist.gov/tf-cgi/servers.cgi 。
(3)rdate -s $ntpServer 同步网络时间可能出现的情况:
# rdate -s 129.6.15.28
rdate: current time matches remote time # 同步成功,返回值为0
# rdate -s 129.6.15.28
rdate: timeout connecting to time server # 超时,返回值为1
# rdate -s 129.6.15.28
rdate: can't connect to remote host (129.6.15.28): Network is unreachable # 无法联网,返回值为1
# rdate -s time.nist.gov
rdate: bad address 'time.nist.gov' # DNS error,返回值为1
# rdate -s 129.6.15.28
rdate: 129.6.15.28: short read # 其它错误,返回值为1
参考文章
date命令 http://man.linuxde.net/date
ntpdate命令 http://man.linuxde.net/ntpdate
《ARM40-A5应用——GPRS模块ppp拨号上网》
《ARM40-A5应用——4G模块EC20-CE拨号上网》
NIST Internet Time Servers https://tf.nist.gov/tf-cgi/servers.cgi
在NTP官方网站官网地址: http://www.pool.ntp.org/en/
《鳥哥的 Linux 私房菜》第十五章、時間伺服器: NTP 伺服器
http://linux.vbird.org/linux_server/0440ntp.php
crontab 定时任务
http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/crontab.html
crontab命令进程和作业管理
http://man.linuxde.net/crontab
阿里云服务器/etc/crontab文件
荟聚计划:共商 共建 共享 Grant