# 时间
如何计算系统时间?
- Linux 主机每次开机时,会从 BIOS 读取硬件时钟,然后根据它设置系统时间。
- BIOS 附带了一个实时时钟(Real-Time Clock ,RTC)芯片,由独立电池供电,即使主机关机也会累计硬件时钟(hardware clock)。
- 主机运行时,会根据 CPU tick 定时器来累计系统时间,因此与 RTC 时间可能存在误差。
- RTC 时间默认采用 UTC 时区,而系统时间默认采用本地时区。
- 硬件时钟不一定准确。主机可以通过 NTP 等网络协议,自动获取最新的 UTC 时间。
如何决定本地时区?
- Linux 系统会读取文件
/etc/localtime
,决定本地时区是哪个时区,然后计算出系统时间。- 例如执行命令
timedatectl set-timezone Asia/Shanghai
,相当于执行ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
。
- 例如执行命令
- 一般软件的时间,会跟随系统时间,但也可采用不同的时区。例如:
- 设置了环境变量
TZ
时,date 命令会根据它决定自己的时区。例如:TZ="America/Los_Angeles" date
- JVM 会读取文件
/etc/timezone
,决定自己的时区。
- 设置了环境变量
- Linux 系统会读取文件
# cal
$ cal # 查看本月的日历
-y # 查看今年的日历
2000 # 查看指定年份的日历
1 2000 # 查看指定月份的日历
# clock
$ clock # 显示硬件时钟
-s # 根据当前的硬件时钟,设置系统时间
-w # 根据当前的系统时间,设置硬件时钟
- 例:
[root@CentOS ~]# clock Fri 06 Dec 2019 08:50:14 AM CST -0.606412 seconds
-0.606412 seconds
表示硬件时钟比系统时间慢了 0.6 秒多。
# date
$ date [OPTION]... [+FORMAT]
-d now # --date ,获取系统时间,默认为 now
-u # --utc ,转换成 UTC 时区
-s "20001201 12:00:00" # --set ,根据字符串设置系统时间
+"%Y-%m-%d %H:%M:%S %N" # 显示成指定格式,这里是年、月、日、时、分、秒、纳秒
+%s # 显示成 Unix 时间戳
- 例:
[root@CentOS ~]# date Fri Dec 6 08:50:14 CST 2019 [root@CentOS ~]# date -d '-3 day' +%Y-%m-%d 2019-12-03
- 修改系统时间可能导致正在运行的进程出错。
# timedatectl
$ timedatectl # 显示关于时间的配置信息
set-time "20001201 12:00:00" # 设置系统时间,并自动更新硬件时钟
set-ntp true # 是否启用 NTP 服务,比如 ntpd 或 chronyd
list-timezones # 显示所有可用的时区
set-timezone Asia/Shanghai # 设置本地时区
- 例:
[root@CentOS ~]# timedatectl Local time: Fri 2021-01-12 10:34:35 CST # 系统时间 Universal time: Fri 2021-01-12 02:34:35 UTC # UTC 时间 RTC time: Fri 2021-01-12 02:34:34 # RTC 时间 Time zone: Asia/Shanghai (CST, +0800) # 本地时区 NTP enabled: yes # 是否启用 NTP 服务 NTP synchronized: yes # 是否已完成 NTP 同步 RTC in local TZ: no # RTC 时间是否采用本地时区 DST active: n/a # 是否启用夏令时
# ntp
:一个工具,实现了网络时间协议(Network Time Protocol ,NTP)。
- 采用 C/S 架构,提供了两个命令:
- ntpd :作为服务器保持运行,默认监听 UDP 123 端口。自动从互联网标准 NTP 服务器同步时间,也可提供时间校准服务给其它 NTP 客户端。
- ntpdate :作为客户端,用于从 NTP 服务器同步时间。
- 安装:
yum install ntp
- 运行 ntpd :
systemctl start ntpd systemctl enable ntpd # firewall-cmd --add-service=ntp # 开通防火墙端口,允许被外部的 NTP 客户端访问
- 运行 ntpdate :
ntpdate pool.ntp.org # 从指定的 NTP 服务器同步时间
- 为了自动同步本机时间,可以保持运行 ntpd 进程,也可以添加一个 crontab 任务去定时执行 ntpdate :
* 0 * * * /sbin/ntpdate pool.ntp.org &>> /var/log/cron @reboot /sbin/ntpdate pool.ntp.org &>> /var/log/cron
- 配置文件位于 /etc/ntp.conf ,内容示例:
restrict default nomodify notrap nopeer noquery # 禁止客户端的一些权限 restrict 127.0.0.1 # 允许被该 IP 的客户端连接,且不禁止权限 restrict ::1 server 0.centos.pool.ntp.org # 添加其它 ntp 服务器,同步其时间,如果同步失败则尝试下一个 server 1.centos.pool.ntp.org server 2.centos.pool.ntp.org server 3.centos.pool.ntp.org minpoll 6 # 与服务器同步时间的最小轮询间隔,单位为 2 秒的幂级数,默认为 2^6 秒 maxpoll 10 # 最大轮询间隔,默认为 2^10 秒
- restrict 规则用于禁止客户端的权限,分为以下几种:
nomodify # 禁止修改服务器的时间 notrap # 禁止 trap 远程登录 nopeer # 禁止对等连接 noquery # 禁止查询服务器的时间 notrust # 禁止未经认证的客户端连接 ignore # 禁止连接
- restrict 规则用于禁止客户端的权限,分为以下几种:
# chrony
:一个与 ntp 类似的工具,但误差更小。
- 在 CentOS 7 中,chrony 已取代 ntp ,默认安装。
- 采用 C/S 架构,提供了两个命令:
- chronyd :作为服务器保持运行,默认监听 UDP 323 端口。
- chronyc :作为客户端,用于与 chronyd 交互。
- 安装:
yum install chrony
- 运行 chronyd :
systemctl start chronyd systemctl enable chronyd
- 运行 chronyc :
chronyc sources # 列出当前采用的 NTP 服务器 tracking # 显示时间同步的状态
- 配置文件位于 /etc/chrony.conf 。