# 时间

  • 如何计算系统时间?

    • Linux 主机每次开机时,会从 BIOS 读取硬件时钟,然后根据它设置系统时间。
    • BIOS 附带了一个实时时钟(Real-Time Clock ,RTC)芯片,由独立电池供电,即使主机关机也会累计硬件时钟(hardware clock)。
    • 主机运行时,会根据 CPU tick 定时器来累计系统时间,因此与 RTC 时间可能存在误差。
      • RTC 时间默认采用 UTC 时区,而系统时间默认采用本地时区。
    • 主机可以通过网络从其它主机同步系统时间,比如使用网络时间协议(Network Time Protocol ,NTP)。
  • 如何决定本地时区?

    • 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 ,决定自己的时区。

# 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

:一个实现了 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    # 禁止连接
      

# chrony

:一个实现了 NTP 协议的工具,比 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 。