一、问题现象
现场一台银河麒麟 V10 服务器出现时区信息异常的问题:设置了正确时区后,每次重启系统时区信息丢失,执行 timedatectl show 查看时间属性时,输出结果中没有 Timezone 时区字段。
同时,点击桌面右下角的时间和日期,进入时间与日期设置界面后,由于系统未能正确识别当前时区,界面会自动选择时区列表中的最后一个选项------圣诞岛。

二、排查过程
1. 查看 systemd-timedated 服务日志
首先查看 systemd-timedated 服务日志。systemd-timedated 是 systemd 提供的系统时间与时区管理服务,负责响应 timedatectl 等客户端以及桌面环境发起的时间、日期、时区和 RTC 配置请求。它不同于 NTP 服务:NTP 主要负责与时间服务器同步系统时钟,而 timedated 负责管理相关配置。
执行以下命令查看服务日志:
journalctl -u systemd-timedated
日志中发现如下报错(原始日志中的英文提示):
/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/.

该提示说明 systemd-timedated 期望 /etc/localtime 是一个指向 /usr/share/zoneinfo/ 目录下时区数据文件的符号链接。由此将排查重点转向 /etc/localtime。
2. 检查 /etc/localtime 文件类型及链接关系
/etc/localtime 是系统本地时区配置文件。常见配置方式是将它设置为指向某个时区数据文件的符号链接,例如指向 Asia/Shanghai。系统的本地时间转换库会读取该文件中的时区数据。
通过 timedatectl set-timezone Asia/Shanghai 修改时区时,systemd-timedated 会更新 /etc/localtime;桌面环境的时间和日期设置功能通常也会通过系统时间管理服务完成时区配置,最终反映到该文件。
使用以下命令检查文件属性:
stat /etc/localtime
readlink /etc/localtime

正常情况下,ls -li通常可以看到下面的符号链接:

而故障情况下中/etc/localtime 并不是符号链接,而是普通文件;进一步查看发现它与 /usr/share/zoneinfo/Asia/Shanghai 具有相同的 inode,说明两个路径指向同一个文件,即形成了硬链接。

这里需要注意:硬链接本身仍然可以读取时区数据,因此系统可能仍能显示正确的本地时间;但 systemd-timedated 无法像解析标准符号链接目标那样可靠地反推出具体时区名称,从而出现 timedatectl show 中没有 Timezone 字段的现象。
3. 配置 Audit,监控 /etc/localtime 的修改
确认文件类型异常后,下一步需要查明是谁修改了 /etc/localtime。Linux Audit 可以记录对指定文件的访问和修改行为,并保留进程、系统调用、文件路径等信息。
现场检查发现内核启动参数中 audit=0,因此需要启用 Audit。排查时临时将 /boot/efi/EFI/kylin/grub.cfg 中生效内核启动项的 audit=0 修改为 audit=1。注意:grub.cfg 通常属于生成文件,直接编辑可能在重新生成 GRUB 配置后被覆盖。正式环境建议通过发行版对应的 GRUB 配置方式修改启动参数,并做好配置备份。
创建 Audit 规则文件:
vim /etc/audit/rules.d/tz_change.rules
在文件中添加以下规则:
-w /etc/localtime -p wa -k tz_change
参数说明:-w 指定监控文件;-p wa 表示监控写入(write)和属性变化(attribute);-k tz_change 为规则设置检索关键字,便于后续查询。
设置 auditd 服务开机自启:
systemctl enable auditd
4. 重启系统 并 确认 Audit 规则生效
完成启动参数和规则配置后重启系统。系统启动后,先检查 Audit 规则是否已经加载,确认监控规则存在,再等待或复现对 /etc/localtime 的修改行为。
auditctl -l
确认输出中包含以下规则:
-w /etc/localtime -p wa -k tz_change
如果没有看到该规则,不应直接进入后续分析;应先检查规则文件内容、augenrules 加载结果以及 auditd 服务状态。
5. 查询审计记录,定位异常进程
使用 ausearch 根据规则关键字检索审计记录。注意关键字应与规则中配置的 tz_change 保持一致:
ausearch -k tz_change

本次审计记录显示,异常操作与一个 PHP 进程有关。为保护用户程序信息,本文对程序名称进行脱敏,统一使用 aaa.php 表示。
6. 分析系统调用,确认硬链接创建行为
从 Audit 日志可以看到,PHP 进程(aaa.php)对 /etc/localtime 进行了文件操作。
结合该事件中的 PATH 记录,可以还原出以下过程:
- 原有 /etc/localtime 软链接被删除。
操作前,/etc/localtime 是正常的符号链接,其 inode 为 1079627968。
- PHP 进程执行 linkat 系统调用,创建硬链接。
同一事件的 SYSCALL 记录显示:
comm="aaa.php"
exe="/usr/bin/php"
arch=c00000b7
syscall=37
success=yes
其中,arch=c00000b7 表示 AArch64 架构,syscall=37 对应 linkat 系统调用,success=yes 表示该系统调用执行成功。

- /etc/localtime 被创建为指向同一 inode 的硬链接。
结合 PATH 记录可以看到,操作涉及:
/etc/localtime
/usr/share/zoneinfo/Asia/Shanghai
新创建的 /etc/localtime 与 /usr/share/zoneinfo/Asia/Shanghai 的 inode 均为 554。这说明二者实际上是指向同一个文件对象的硬链接,而不再是原来的符号链接。这与前面发现的 /etc/localtime 文件类型异常相互印证。
7 . 后续处理
通过 Audit 已定位到执行异常文件操作的 PHP 进程,且进程对应用户业务程序。由于该程序存在多层文件引用和调用关系,具体是哪一段业务代码触发 linkat,需要由程序维护方结合源代码及调用链进一步排查。
因此,本案例的排查结论:已确认 /etc/localtime 被替换为硬链接,并通过 Audit 定位到执行 linkat 的 PHP 进程;具体业务代码触发点仍需程序维护方进一步确认。
三、问题总结
本次故障是 /etc/localtime 的文件类型和链接关系发生了异常变化。原本用于标识时区的符号链接被替换为硬链接,导致 systemd-timedated 无法正常识别具体时区名称,最终表现为 timedatectl show 不显示 Timezone,桌面时间和日期设置界面也无法正确获取当前时区。
本次排查的关键思路可以归纳为:
- 先从服务日志入手,依据 systemd-timedated 的报错锁定 /etc/localtime。
- 再通过 ls、stat、readlink 检查文件类型、inode 和链接关系,确认符号链接异常。
- 使用 Audit 对关键文件进行监控,通过进程信息和系统调用定位修改行为。
- 结合 ARM64 架构的系统调用号、PATH 记录和 inode 对比,确认用户程序的硬链接创建行为。
提示:本文中的 aaa.php 为脱敏后的程序名称;实际排查时应保留完整 Audit 原始事件,并结合具体发行版、内核架构和 Audit 版本核对系统调用信息。
