应统一用sudo timedatectl set-timezone asia/shanghai修复时区,避免timedatectl与/etc/localtime不一致;检查tz环境变量、重启journald/rsyslog服务,并验证java/mysql/docker等应用层时区是否同步。

日志时间混乱,八成是时区配置没对齐,不是时间不准,而是系统“以为”的本地时间错了。
确认 timedatectl 与 /etc/localtime 是否一致
这是最常被忽略的第一步:系统声称的时区和实际生效的时区可能不一致。比如 timedatectl status 显示 Time zone: Etc/UTC,但 ls -l /etc/localtime 却指向 /usr/share/zoneinfo/Asia/Shanghai,说明底层软链接被手动改过,而 systemd 并未感知。
- 运行
timedatectl show --property=Timezone --value获取当前 timedatectl 记录的时区名 - 运行
ls -l /etc/localtime查看软链接目标路径 - 对比两者是否匹配;若不匹配(如一个写
Asia/Shanghai,另一个是Etc/UTC),说明配置处于撕裂状态 - 不要手动
cp或ln -sf覆盖/etc/localtime,应统一用sudo timedatectl set-timezone Asia/Shanghai
检查 TZ 环境变量是否意外覆盖
某些服务(如 rsyslog、自定义脚本、容器启动命令)会通过 TZ 环境变量强行指定时区,优先级高于系统设置,导致日志时间“局部错乱”。
- 全局搜索:
grep -r "TZ=" /etc/environment /etc/profile* /etc/systemd/system/*.service 2>/dev/null - 检查特定服务环境:
systemctl show --property=Environment rsyslog | grep TZ - 临时验证:在 shell 中执行
TZ=UTC date和TZ=Asia/Shanghai date,观察输出差异 - 若发现非预期的
TZ设置,注释或删除对应行,然后sudo systemctl daemon-reload && sudo systemctl restart rsyslog
验证 journald 和 rsyslog 是否已重载新时区
修改系统时区后,journald 和 rsyslog 不会自动刷新时区上下文——它们在启动时读取一次,之后就缓存了格式化逻辑。
- 重启日志服务:
sudo systemctl restart systemd-journald rsyslog - 立即验证新日志时间戳:
journalctl --no-pager -n 5,确认Local time字段已按预期偏移(如从 UTC 变为 +0800) - 若仍显示 UTC 时间,检查 journal 是否被强制使用 UTC:
journalctl --utc -n 5对比;--utc是显示选项,不影响存储,但说明你可能在用错命令 - rsyslog 需确认模板未硬编码时间格式,检查
/etc/rsyslog.conf或/etc/rsyslog.d/*.conf中是否有$ActionFileDefaultTemplate或template定义含%timestamp:::date-rfc3339类字段
注意 Java、MySQL、Docker 这些“时区绝缘体”
系统时区改了,不代表应用就跟着变。它们往往在启动时固化时区,后续系统变更无效。
- Java 应用:JVM 启动后不会响应系统时区变化,必须重启;可加
-Duser.timezone=Asia/Shanghai显式锁定 - MySQL:运行
SELECT @@global.time_zone, @@session.time_zone;;若返回SYSTEM,它才跟随系统;否则需在my.cnf中设default-time-zone = '+08:00' - Docker 容器:默认继承宿主机
/etc/localtime,但如果镜像内已有TZ环境变量(如openjdk:17镜像自带TZ=UTC),就会覆盖宿主机设置;启动时加-e TZ=Asia/Shanghai或挂载/etc/localtime:/etc/localtime:ro
真正麻烦的从来不是改时区这个动作,而是改完之后谁信、谁不信、谁缓存了旧值、谁又偷偷覆盖了——得一层层验过去,不能只看 date 命令输出就认为万事大吉。











