代码之家  ›  专栏  ›  技术社区  ›  AsamRegnat

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

  •  1
  • AsamRegnat  · 技术社区  · 7 年前

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

    我试着看看 /etc/localtime 已断开,但它是指向的正确软链接 /usr/share/zoneinfo/<timezone> (本例中为欧洲/柏林)。 我已经检查了时区文件 zdump 文件内容正确无误。系统的时区和时间也可以使用 date 。没有定义 $TZ 在我的bash或任何其他地方都有变量!

    作为一个附加测试,我运行了以下代码,包括 $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
    

    因此,似乎无法找到“欧洲/柏林”时间,因为显示的是UTC时间,“欧洲”时区无效。

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

    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、 美国相同 gcc版本4.4.7 在两台机器上都使用。

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

    1 回复  |  直到 7 年前
        1
  •  0
  •   AsamRegnat    7 年前

    我终于明白了,问题是 libc.so 库,该库为其中一台机器进行了不同的编译,仅用于除linux之外的一些C应用程序。这就解释了为什么 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系统正在使用 日期 或某些应用程序,但使用C程序输出错误。

    解决方案 :确保代码中没有编程错误后,请检查

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

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