C 程序使用 GCC 在 Linux 上仅提供 UTC 时间作为本地时间

C program delivers only the UTC time as localtime on Linux using GCC

我有一个 C 程序 运行 在配置了相同时区的两个不同的 RHEL6 服务器上运行。 C 程序使用 time.h 中的时间函数。在其中一台服务器上正确确定了本地时间,在另一台服务器上显示的 UTC(默认)时间独立于配置的时区。

我试着看看 link 到 /etc/localtime 是否坏了,但它是一个正确的 softlink 到 /usr/share/zoneinfo/<timezone> (在这种情况下 Europe/Berlin). 我用 zdump 检查了时区文件,文件的内容是正确的。使用 date 也可以正确显示系统的时区和时间。在我的 bash 或其他任何地方都没有 $TZ 变量的定义!

作为附加测试,我有 运行 以下带有和不带有 $TZ 变量的代码:

    ::time_t aclock;
    ::tm tm_tmp;
    ::tm *newtime;

    setenv("TZ", "Europe/Berlin", 1);
    tzset();
    ::time( &aclock );
    newtime = ::localtime_r( &aclock, &tm_tmp );
    printf("\nDEBUG TIME: %d ", aclock);
    printf("\nDEBUG TIMEZONE: %s \n", newtime->tm_zone);
    printf("DEBUG HOUR: %d \n", newtime->tm_hour);

使用上面的代码并以不同的方式设置 TZ 参数,我在 故障 服务器上得到以下输出,假设此时服务器时间是 Europe/Berlin, CEST

without setenv:
DEBUG TIME: 1524241319
DEBUG TIMEZONE: UTC
DEBUG HOUR: 16

setenv("TZ", "Europe/Berlin", 1);
DEBUG TIME: 1524241319
DEBUG TIMEZONE: Europe
DEBUG HOUR: 16

setenv("TZ", "/etc/localtime", 1);
DEBUG TIME: 1524241319
DEBUG TIMEZONE: CEST
DEBUG HOUR: 18

看来找不到 "Europe/Berlin" 时间,因为显示的是 UTC 时间,而时区 "Europe" 无效。

正如我所说,另一台机器上的输出/行为是预期的:

without setenv:
DEBUG TIME: 1524241711
DEBUG TIMEZONE: CEST
DEBUG HOUR: 18

setenv("TZ", "Europe/Berlin", 1);
DEBUG TIME: 1524241711
DEBUG TIMEZONE: CEST
DEBUG HOUR: 18

setenv("TZ", "/etc/localtime", 1);
DEBUG TIME: 1524241711
DEBUG TIMEZONE: CEST
DEBUG HOUR: 18

P.S。两台机器上使用相同的 gcc 版本 4.4.7

有没有可能是我的时区数据库在故障服务器上损坏了?有人遇到过类似问题并解决了吗?

我终于弄清楚,问题出在 libc.so 库,它针对其中一台机器进行了不同的编译,并且只用于某些 C 应用程序,linux 他自己除外。这解释了为什么 date 提供了 wright 输出但 C 程序没有。 使用 ldd libc.so 我发现链接器也被设置为默认路径 /home/mqm/lib,这不适合我的服务器 /home/mqm/lib/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2。要恢复,这里是完整的解决方案:

问题:您的 Linux 系统使用 date 或某些应用程序提供正确的日期和时间,但使用 C 程序输出错误。

解决方法:确保你的代码没有编程错误后,再用

检查

strace -e trace=open,close,read,write,connect,accept yourCProgram

哪个路径用于获取time/timezone。您还可以检查 ldd libc.so 以查看链接器的默认路径在哪里。 如果路径与您的 linux 系统配置不对应,请考虑重新编译 C 库以适合您的系统配置或将 $TZ='fullpathtotimezone' 设置为修补程序/解决方法。