2013年3月13日星期三

Linux,有关时间

RT
被 Linux 的时区、夏令时设置折磨地相当痛苦,网上四处 Goolge,加上各种试验,收获不小,特整理在此。

1. GMT 和 UTC
GMT 即 Greenwich Mean Time,格林威治标准时间。
UTC 即 Coordinated Universal Time,世界协调时间(又称世界标准时间、世界统一时间)。
在一般精度要求下,两者是一样的,即 GMT≈UTC,但 UTC 是以原子钟校准的,更精确。

2. 夏令时(DST)
所谓夏令时(DST,Daylight Saving Time),就是在夏天这样日照时间比较长的时期,人为地将时钟调快一个小时,目的是为了充分利用光照,减少电力照明。欧美一些国家把这个夏令时写入了法律,近年来已经开始实施。
注意,这是人为的,所以 UNIX 元年计时不遵循这个规则,无论是否在使用夏令时的地区。
在 Linux 上,是通过控制时区的 /etc/localtime 文件来调整夏令时,调整起来有点麻烦,好像必须替换时区配置文件,不知道有没有简单的方法,请知道的同学告知。
而在 Windows 上,如果设置成支持夏令时的地区,那么配置页左下角会有个勾选框,可以取消来不使用夏令时,这个倒是简单。
查看 Linux 上时区配置文件的夏令时设置很简单,使用如下命令即可:
    zdump -v Time_Zone_Name
比如,查看 EST5EDT(美国东部夏令时)的
    zdump -v EST5EDT
这会打印出历年夏令时的起始和终止的时间(范围)。

3. 系统时间(System Time)、硬件时间
也叫系统时钟、硬件时钟,实际上按使用到的命令来说,叫时钟更合理,就如显示和设置硬件时钟的命令 hwclock ,就是 hardware clock 的缩写。
在 Linux 系统中,所谓系统时间,是由系统自行维护的一个时间,默认情况下,系统以及应用程序使用的就是这个系统时间。命令 date 改变的也是这个系统时间,除非使用 hwclock 将系统时间同步到主板上的硬件时钟或者直接修改硬件时钟,否则主板上的硬件时钟不会被改变。
主板上的硬件时钟由电池自动维持着,所以机器断电也不会影响。
系统时间在 Linux 系统每次开机时都会被重新初始化——内核从主板上的硬件时钟获取,并根据时区、夏令时等设置进行调整,然后自行维护这个系统时钟,直到机器下次关机或重启。

4. Localtime (本地时间) 和 UTC
本地时间 = 硬件时钟 + 时区调整 + 夏令时(如果有)调整
在 Linux 系统中,是否使用 UTC ,决定着内核维护系统时间的两种截然不同的方式:
UTC 方式: /etc/sysconfig/clock 中 UTC=true
       开机: BIOS------->UTC(将BIOS中的时间看成是UTC)------(时区+夏令时变化)----->CST
       关机: CST -------(
逆运算时区+夏令时变化)----->UTC-------存储到------>BIOS

 Localtime 方式: /etc/sysconfig/clock 中 UTC=false
       开机: BIOS---------------------->CST(将BIOS中的时间看成是CST)
       关机: CST ---------存储到------>BIOS


其中,Windows 只使用 Localtime 方式,也就是说,如果双系统并存,Linux 的时间设定必须选用 Localtime 方式,否则会导致硬件时钟设定混乱。


在 Linux 中,启动时设定时钟的部分位于 /etc/rc.d/rc.sysinit 脚本中:
# Set the system clock.
update_boot_stage RCclock
ARC=0
SRM=0
UTC=0

if [ -f /etc/sysconfig/clock ]; then
   . /etc/sysconfig/clock

   # convert old style clock config to new values
   if [ "${CLOCKMODE}" = "GMT" ]; then
      UTC=true
   elif [ "${CLOCKMODE}" = "ARC" ]; then
      ARC=true
   fi
fi

CLOCKDEF=""
CLOCKFLAGS="$CLOCKFLAGS --hctosys"

case "$UTC" in
    yes|true)   CLOCKFLAGS="$CLOCKFLAGS --utc"
                CLOCKDEF="$CLOCKDEF (utc)" ;;
    no|false)   CLOCKFLAGS="$CLOCKFLAGS --localtime"
                CLOCKDEF="$CLOCKDEF (localtime)" ;;
esac
case "$ARC" in
    yes|true)   CLOCKFLAGS="$CLOCKFLAGS --arc"
                CLOCKDEF="$CLOCKDEF (arc)" ;;
esac
case "$SRM" in
    yes|true)   CLOCKFLAGS="$CLOCKFLAGS --srm"
                CLOCKDEF="$CLOCKDEF (srm)" ;;
esac

[ -x /sbin/hwclock ] && /sbin/hwclock $CLOCKFLAGS

action $"Setting clock $CLOCKDEF: `date`" /bin/true


相关配置文件就是 /etc/sysconfig/clock


5. Linux 上的相关命令
查看系统时间
    date

查看 UNIX 元年计时
    date +%s
注意:这个可不受夏令时调整的影响,就是自1970年1月1日0点0分0秒到现在系统时间的秒数,再次重申,没有夏令时调整影响。

时区选择
    tzselect
我个人比较喜欢直接复制 /usr/share/zoneinfo/ 下对应的 zone 文件替换 /etc/localtime 的方式来实现。

将系统时间与时间服务器进行同步
    ntpdate time.windows.com 
PS: 这里使用的是 windows 的时间服务器……


将系统时间写入硬件时间
    hwclock --systohc

将硬件时间同步到系统时间
    hwclock --hctosys 

6. hwclock 命令
6.1. 显示时间
如果要显示硬件时钟,很简单:
    hwclock
这相当于
    hwclock --show 或者 hwclock -r
除非手动更改过系统时间或者长时间没有与硬件时钟同步,那么两者应该是一样的。
其实使用 hwclock 显示时间并不是这么简单的,这与 Linux 内核维护系统时间的方式有很大关系。
首先说一下 hwclock 命令涉及到的配置文件:
    /etc/sysconfig/clock    # 机器启动、系统初始化时,Linux 内核设置系统时间要读取的配置文件
    /etc/adjtime    # 使用 hwclock 命令上一次成功设置(--set, --systohc or --adjust)硬件时钟时使用的选项保存在该文件中
    /etc/localtime    # 时区设定文件,如有夏令时,则也包括夏令时设定
其实 hwclock 命令的功能选项,都应该加上 --utc 或者 --localtime ,以此来表示使用何种方式来操作硬件时钟,默认情况下,Linux 内核使用何种方式维护系统时间,hwclock 就应该使用同样的方式。而这个默认情况下 hwclock 使用的选项,就保存在上面提到的 /etc/adjtime 中。
因此,以 Linux 内核使用 UTC 方式(硬件时钟中保存的是 UTC 0 时区的时间)维护系统时间为例:
    hwclock --show  就相当于  hwclock --show --utc
    hwclock --systohc  就相当于  hwclock --systohc --utc
    hwclock --hctosys  就相当于  hwclock --hctosys --utc
在这种情况下,hwclock 显示时间过程应是:
读取硬件时钟,根据 /etc/localtime 中指定的时区和夏令时(如果有)设定,计算得到当前时间。
那么如果直接指定 --localtime 会怎样呢?
    hwclock --show --localtime
过程如下:
因为给 hwclock 提供了 --localtime 选项,那么 hwclock 就不会再去找 /etc/adjtime 文件中的配置了。按照 Localtime 维护时间的方式(认为硬件时间就是系统时间,就是本地时间),读取硬件时钟,然后显示出来。因为本例中, Liunx 内核维护时间的方式是 UTC,所以硬件时钟存储的就是 UTC 0 时区的时间,所以显示出来的就是 UTC 时间。

6.2. hwclock 的 --localtime 选项
Indicates that the Hardware Clock is kept in Coordinated Universal Time or local time, respectively.  It is your choice  whether to keep your clock in UTC or local time, but nothing in the clock tells which you’ve chosen.  So this option is how you give that information to hwclock.

 6.3. 使用 hwclock --systohc 同步硬件时钟
本例中,Linux 内核维护系统时间的方式是 UTC。
我们这里使用如下命令来同步硬件时钟:
    hwclock --systohc --localtime
这会发生什么情况呢?
首先,hwclock 读取系统时间(就是 UTC 时间+时区变化+夏令时变化计算得到的那个本地时间),因为我们给 hwclock 指定了 --localtime ,所以 hwclock 会忽略 /etc/adjtime 文件中的配置,并以 Localtime 方式来计算硬件时间,而这种方式很简答,直接认为系统时间就是硬件时间,所以直接将读取的系统时间同步到了硬件时钟,最后更新 /etc/adjtime 文件的配置,在这之前,/etc/adjtime 中应该记载着维护系统时间的方式是 UTC,而此时会被更新为 LOCAL 。
那么此时,使用 hwclock --show 或 hwclock --show --localtime 查看系统时间,会发现和使用 date 看是一样的,具体过程见小标题 4 。但是使用 hwclock --show --utc 看,则结果会很不同,首先,hwclock 读取硬件时间,此时的硬件时间和系统时间是一样的,然后 hwclock 根据 /etc/localtime 中时区以及夏令时配置,逆运算,得到 UTC 0 时区的时间。


PS: 参考了很多的文章和博客,过于繁多,就不一一写出了,这是网上写 Blog 的好处之一,不用像科学论文那样去考虑文献出处,抄袭或者其他~好吧,我只是总结在此,希望以后自己查着方便,也希望后来者看到后有所帮助……

没有评论:

发表评论

使用 Charles 及旧版本 iTunes 下载旧版本 iOS APP

注意:吾爱破解论坛发布的一系列自动化下载软件,比如 iOS APP Store 旧版应用下载 5.1 什么的都不好用,目前只能手动通过 Charles 截留并修改旧版本 iTunes HTTPS 请求达到下载旧版本应用的目的。 从 iOS APP Store 下载的软件都是与用户...