如何调整阿里云函数计算容器内的时区

# 简介

最近在接触阿里云函数计算时发现线上时间与本地时间相差 8 小时, 推断是线上所使用的的时区不是 GMT+8 时区导致的.

想要解决这个问题, 首先要了解函数计算线上操作系统的类型, 再根据不同的发行版找到对应的设置时区的方法.

aliyun 2020 promotion (opens new window)

# 获取函数计算容器的发行版代号

通过 fun install sbox -i -r custom 指令启动一个可交互的函数计算沙盒, 在沙盒中执行 uname -a 即可获得容器的发行版代号.

$ uname -a
Linux fc-custom 4.19.76-linuxkit #1 SMP Tue May 26 11:42:35 UTC 2020 x86_64 GNU/Linux

Emmmm, 函数计算似乎使用了自定义的发行版.

# 根据发行版设置时区

由于函数计算容器使用的是自定义发行版, 因此我们需要尝试 多种可能的 设置时区的方式.

根据 fun install 相关文档 (opens new window), 我们可以知道 FC 容器可以调用 apt (opens new window). 因此, 我们可以推断 FC 容器里的发行版可能是基于 Debain 或者 Ubuntu 改造的.

# Ubuntu ?

根据 Ubuntu 手册: localtime (opens new window):

The /etc/localtime file configures the system-wide timezone of the local system that is used by applications for presentation to the user.

It should be an absolute or relative symbolic link pointing to /usr/share/zoneinfo/, followed by a timezone identifier such as "Europe/Berlin" or "Etc/UTC".

The resulting link should lead to the corresponding binary tzfile(5) timezone data for the configured timezone.

Because the timezone identifier is extracted from the symlink target name of /etc/localtime, this file may not be a normal file or hardlink.

The timezone may be overridden for individual programs by using the $TZ environment variable. See environ(7).

You may use timedatectl(1) to change the settings of this file from the command line during runtime.

Use systemd-firstboot(1) to initialize the time zone on mounted (but not booted) system images.

在沙盒中尝试通过 timedatectl 调整时区时提示找不到指令, 看来不是基于 Ubuntu 改造的.

$ datetimectl
bash: datetimectl: command not found

# Debian ?

根据 Debian 文档: TimeZoneChanges (opens new window):

To see or change what timezone your Debian system is configured for, use dpkg-reconfigure tzdata

尝试在沙盒环境中调用 dpkg-reconfigure tzdata:

$ dpkg-reconfigure tzdata

Current default time zone: 'Etc/UTC'
Local time is now:      Thu Jul  9 09:14:51 UTC 2020.
Universal Time is now:  Thu Jul  9 09:14:51 UTC 2020.

🎉 Bingo

文档中提到默认的时区文件放在 /usr/share/zoneinfo 文件夹下, 并且 /etc/localtime 文件是一个软连接

$ ls /usr/share/zoneinfo
Africa      CET      Egypt    GMT+0      Iran       MST7MDT  Poland     US                 localtime
America     CST6CDT  Eire     GMT-0      Israel     Mexico   Portugal   UTC                posix
Antarctica  Canada   Etc      GMT0       Jamaica    NZ       ROC        Universal          posixrules
Arctic      Chile    Europe   Greenwich  Japan      NZ-CHAT  ROK        W-SU               right
Asia        Cuba     Factory  HST        Kwajalein  Navajo   Singapore  WET                zone.tab
Atlantic    EET      GB       Hongkong   Libya      PRC      SystemV    Zulu               zone1970.tab
Australia   EST      GB-Eire  Iceland    MET        PST8PDT  Turkey     iso3166.tab
Brazil      EST5EDT  GMT      Indian     MST        Pacific  UCT        leap-seconds.list

$ ls /etc/localtime -l
lrwxrwxrwx 1 root root 27 Jul  9 09:26 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC

既然如此, 那我们尝试将 /etc/localtime 指向其他时区文件试试呢?

$ date -R
Thu, 09 Jul 2020 09:33:23 +0000

$ rm /etc/localtime && ln /usr/share/zoneinfo/Asia/Shanghai /etc/localtime -s

$ date -R
Thu, 09 Jul 2020 17:34:32 +0800

🎉 修改时区成功.

# 最佳实践

最近在钉钉群里潜水的时候, 有人提到可以通过设置环境变量 TZ 来修改时区:

$ export TZ=Asia/Shanghai

后来试验了一下发现确实可以, 比上面修改 /etc/localtime 要方便一些.

# 参考

# 推广

欢迎加入 Spring Cloud 交流群: 617143034 (opens new window)

欢迎大家点击下方的图片领取限量 阿里云优惠券 (opens new window), 新购续费更优惠: 限量阿里云优惠券 (opens new window)