我正在寻找一种便携式/强大的方法来获取Linux机器(主要是不同版本的Debian)的时区,以大陆/城市的形式,例如欧洲/基辅。
到目前为止,我使用的是timedatectl status | grep zone | cut -d' ' -f10
这种方法的问题是它适用于 Debian 9,但不适用于 Debian 10(可以使用 docker 映像轻松检查)。
有没有更好、更通用/可移植的方法来做到这一点(更好的是无需刮擦/解析另一个命令的输出)?如果没有,我应该如何修改上面的命令,以便它在 Debian 9 和 10 上都有效。
答案1
timedatectl status | awk '/zone/ {print $3}'
答案2
地理时区名称既是抽象的又是方便的。在底层,时区数据文件是二进制文件,其中列出了偏移量、不连续性和 DST 更改,但没有列出位置(即使文件名指示了它,因此存在问题/etc/localtime
)。有一个来自位置的映射和日期到时区偏移量,但它不是 1:1 – 例如,给定输出date
,您无法轻松且确定地导出正在使用的地理位置(但您可以计算当前日期的一组兼容位置;或者您可以使用一些努力,检查较早的日期是否存在不连续性,以便推断出位置)。
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/London -0:01:15 - LMT 1847 Dec 1 0:00s
0:00 GB-Eire %s 1968 Oct 27
1:00 - BST 1971 Oct 31 2:00u
0:00 GB-Eire %s 1996
0:00 EU GMT/BST
Link Europe/London Europe/Jersey
Link Europe/London Europe/Guernsey
Link Europe/London Europe/Isle_of_Man
创建二进制Europe/London
文件时,将处理指示的规则以构建时间规则(发生更改的时间戳,用 进行检查zdump -v Europe/London
),并且相关位置会被别名。来自上述任何位置的文件内容或输出将无法区分 localtime
。date
抽象可以让您及时处理法律变更,例如
# TZ=Europe/Andorra date -d "Aug 31 1984"
Fri Aug 31 00:00:00 CET 1984
TZ=Europe/Andorra date -d "Aug 31 1985"
Sat Aug 31 00:00:00 CEST 1985
(安道尔不在欧盟,但自 1985 年起遵循欧盟 DST 规则)
/etc/localtime
是(二进制)时区数据文件,在 Debian 上,按照惯例,它应该是指向指定地理时区文件的符号链接(根据''拉紧''(9) 和《巴斯特》(10)localtime
手册页:
/etc/localtime 文件配置本地系统的系统范围时区,应用程序使用该时区来呈现给用户。它应该是指向 /usr/share /zoneinfo/ 的绝对或相对符号链接,后跟时区标识符,例如“Europe/Berlin”或“Etc/UTC”。生成的链接应指向已配置时区的相应二进制 tzfile(5) 时区数据。
由于时区标识符是从 /etc/localtime 的符号链接目标名称中提取的,因此该文件可能不是普通文件或硬链接。
假设情况是这样:
if [ -L /etc/localtime ]; then
IFS=/ read -a TZFILE < <(readlink -f /etc/localtime)
printf -v TZNAME "%s/%s\n" ${TZFILE[-2]} ${TZFILE[-1]}
echo $TZNAME
fi
在早期版本中(或者如果有人没有遵循文档)它是复制时区数据文件的。因此,为了验证这一点/etc/localtime
并/etc/timezone
同意您需要比较它们:
$ diff -s /etc/localtime /usr/share/zoneinfo/`cat /etc/timezone`
Files /etc/localtime and /usr/share/zoneinfo/America/New_York are identical
如果您需要倒退或彻底:
read CHECK file < <(sha256sum /etc/localtime)
while read sum file; do
[[ "$sum" == "$CHECK" ]] && printf "%s\n" "$file"
done < <(find /usr/share/zoneinfo/ -type f |xargs sha256sum)
这不是一个真正可移植的答案(POSIX 没有定义或要求这些长名字,它们来自 ICANN/IANA),并且您正在systemd
这些版本的 Debian 上使用命令。
答案3
/etc/timezone
您可以从文件中获取时区:
cat /etc/timezone
答案4
这在 Unix 和 Mac 机器上都很有效:
readlink /etc/localtime | awk -F'/' '{print $(NF-1)"/"$(NF)}'