Linux时区配置

1,102 阅读4分钟

在使用Linux操作系统或者容器的时候,我们可能会发现时间差了8个小时,这就说明系统或者容器时区配置存在问题。

1,查看时间与时区

我们使用date命令即可查看当前系统时间与时区:

image-20241225204121404

最后的CST就表示中国标准时间时区。

如果你的输出显示的是UTC,就说明你的时区为世界标准时间,通常会比北京时间早8小时:

image-20241225204300243

2,修改时区

在修改时间之前,我们需要确保系统已安装tzdata软件包,该软件包包含了全部时区的信息:

# 若不是root用户,请在命令前加上sudo
# Debian系操作系统
apt install tzdata

# Alpine操作系统
apk add tzdata

安装完成后,所有的时区数据都在/usr/share/zoneinfo目录下:

image-20241225204741795

修改时区通常有两种方式,这里分别进行讲解,大家视情况选择其一即可。

(1) 链接/etc/localtime文件

将时区数据/usr/share/zoneinfo想要配置的时区文件链接到/etc/localtime文件即可,例如我们需要配置中国时区,通常将/usr/share/zoneinfo/Asia/Shanghai链接到/etc/localtime文件即可:

ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

执行命令后,可以发现时区已成功配置:

image-20241225205255223

/usr/share/zoneinfo目录下,Asia目录存放全部亚洲地区的时区数据,其它目录类似,存放其它世界区域的时区数据。

(2) 使用TZ环境变量

直接指定TZ环境变量为标准时区名称也可以实现时区修改,例如配置为中国标准时间:

# Bash终端
export TZ="Asia/Shanghai"

# Fish终端
set -x TZ "Asia/Shanghai"

结果:

image-20241225205911083

那么如何知道有哪些标准时区名称呢?事实上我们看一下/usr/share/zoneinfo目录即可,例如:

  • 中国标准时间对应的时区文件是/usr/share/zoneinfo/Asia/Shanghai,那么就可以推断出其标准时区名称是Asia/Shanghai
  • 美国纽约时间对应的时区文件是/usr/share/zoneinfo/America/New_York,那么就可以推断出其标准时区名称是America/New_York
  • 新加坡标准时间对应的时区文件是/usr/share/zoneinfo/Singapore,那么就可以推断出其标准时区名称是Singapore

需要注意的是:

  • 使用TZ环境变量配置的时区仅在当前终端会话有效,关闭或者重启终端会失效,而链接/etc/localtime文件是永久生效的
  • TZ环境变量的优先级是最高的

3,/etc/timezone配置文件

/etc/timezone配置文件也是和时区配置有关的文件,其中包含文本形式的时区配置:

image-20241225210843585

但需要注意的是:该配置文件通常并不是用于配置系统时区的,而是一些应用程序通过读取该文件来确定时区,该文件中仅包含所使用的时区的标准时区名称。

在一些操作系统中,可能并不存在该文件。

4,容器时区配置

通常我们运行Docker容器时会发现很多容器内时区使用的是UTC时间,这可能影响我们数据库或者日志输出的时间等,因此在制作镜像或者运行容器时,需要做一些时区的配置。

(1) 制作镜像的时区配置

在编写Dockerfile时,我们可以通过RUN指令安装tzdata,并配合TZ环境变量实现镜像默认的时区配置,假设你是用的是Debian系列镜像:

FROM debian
# 设置DEBIAN_FRONTEND为noninteractive,避免安装tzdata时出现交互式配置
ENV DEBIAN_FRONTEND=noninteractive
# 安装tzdata
RUN apt update \
	&& apt install -y tzdata
# 配置时区环境变量
ENV TZ="Asia/Shanghai"
# ...

可见在安装tzdata时,我们需要先将DEBIAN_FRONTEND环境变量设置为noninteractive,否则安装时会出现配置时区的交互性选项,导致制作镜像失败。如果你用的是Alpine作为基本镜像,那就不会出现该问题。

(2) 运行容器时的时区

如果镜像已经包含tzdata软件包,那么我们运行容器时直接指定TZ环境变量即可:

docker run -id --name xxx -e TZ="Asia/Shanghai" ...

在容器中,使用TZ环境变量的方式会更加方便。