Linux时区错乱引起的故障

今天系统中的某个逻辑突然出现了问题,设备状态一下子成了[超时]状态。恰巧的是更新了一个程序后出现,而且就这个程序所在的模块出现问题,被这个[巧合]害死了。

开始排查更新的代码,仔细检查没有任何问题,在测试机器上和本机上都能正常运行。忽然,想到[超时]一定会与时间有关系,看了一眼服务器时间,果然比我们这个时区的时间慢了13个小时。手动修复了时间,系统正常了。但是,百思不解的是服务器都有NTP时间同步,基本不会出现这个问题。

手动执行了一下NTP同步命令,这才发现就是由于执行这个NTP命令引起了[时间慢]的。公司的服务器都有NTP同步,别的设备没有出现[时间变慢]的现象,唯独这台设备。一定是这台设备的某些[配置不当]或者[什么故障]引起的。经同事提示,发现这台设备的时区和NTP的时区不一致。修改成CST时区,故障派出。

 

修改时区用到的几个命令:通过tzselect命令选择,没有生效 ,  直接修改文件搞定。

$>  vi /etc/sysconfig/clock
修改ZONE属性为 [Asia/Shanghai]
保存退出,如果系统中没有这个文件就跳过。

然后执行一个软连接,让配置生效。这个步骤是关键。
$> ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

修改完了时区,有些应用程序要重启后才生效。。

很奇怪,为啥时区突然混乱了呢?

模仿Linux上的Cal程序

命令行下的calendar工具

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <unistd.h> 
#include <string.h> 
/**************************** 
 * 
 * 模仿Linux 下的  cal命令 
 *  
 * cal 
 * 无参数显示当前月日历 
 * -h      帮助信息 
 * -m      指定月(1--12) 
 * -y      指定年(>1900) 
 * -j      显示本年的第几天,默认显示日期 
 * -y,-m   缺省为当前年、月 
 *  
 * for example: 
 *  
 * $>cal -y 1997 -m 12 
 * $>cal -y 1997 
 * $>cal -m 12 
 * $>cal -y 2008 -j 
 *  
 *  
 * 操作系统对year的限制不同 
 * Window  :一般从1970~2038 
 * Linux   : 基本没有限制 
 *  
 *  
 *  
 * author:zhanglihai 
 * date  : 2008/02/20 
 * **************************/ 
//定义月的英文描述 
char *month_name_en[12]={"January","February","March","April","May","June","July","August","September","October","November","December"}; 
char *week_name_en[7]={"Sun", "Mon", "Tue","Wed", "Thu", "Fri", "Sat"}; 
char *animals[12] = { "鼠", "牛", "虎", "兔", 
                        "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" }; 
int   month_max_day[12]={31,28,31,30,31,30,31,31,30,31,30,31}; 
typedef struct tm Date; 
typedef struct tm *PDate; 
 
 
 
void printHelp(){ 
        printf("\n模仿Linux 下的  cal命令" 
                        "\n\n" 
                        "cal\n" 
                        "无参数显示当前月日历" 
                        "\n\n" 
                        "-h      帮助信息\n" 
                        "-m      指定月(1--12)\n" 
                        "-y      指定年(>1900)\n" 
                        "-j      显示本年的第几天,默认显示日期\n" 
                        "\n\n" 
                        "-y,-m   缺省为当前年、月\n" 
                        "\n" 
                        "for example:\n" 
                        "$>cal -y 1997 -m 12\n" 
                        "$>cal -y 1997\n" 
                        "$>cal -m 12\n" 
                        "$>cal -y 2008 -j \n" 
                        "\n" 
                        "操作系统对year的限制不同\n" 
                     "Window  :一般从1970~2038\n" 
                        "Linux   : 基本没有限制\n" 
                        "\n\n" 
                        "                                           author : zhanglihai\n" 
                        "                                           date   : 2008/02/20\n");         
} 
 
 
int monthMaxDay(int y,int m){ 
        int y1=y+1900; 
        if(m==1) 
        { 
           if((y1%400==0)||(y1%4==0&&y1%100!=0)) 
             return 29; 
        }         
        return month_max_day[m]; 
} 
 
void printYearCal(PDate pdate,int fmt) 
{ 
        int i,j,w,left; 
        int m_len; 
        int max_day1,max_day2; 
        int day1,day2,gday1,gday2; 
        int wday1,wday2; 
        int year=pdate->tm_year; 
        time_t _tm; 
        PDate  _pdate; 
                    pdate->tm_mon=0; 
                    pdate->tm_mday=1; 
                   _tm=mktime(pdate); 
                 if(_tm==-1) 
                 { 
                   printf("can't   mktime . \n"); 
                   printf("-h    help info.\n"); 
                   return;         
                 } 
        printf("\n%*d %s\n\n",(27*2-4*2-4)/2+10,pdate->tm_year+1900,animals[((pdate->tm_year+1900)-4)%12]); 
                   _pdate=localtime(&_tm); 
                   wday1=_pdate->tm_wday; 
        day1=day2=gday1=gday2=1; 
        for(i=0;i<12;i+=2) 
        { 
                    day1=day2=1; 
                    max_day1=monthMaxDay(year,i); 
         max_day2=monthMaxDay(year,i+1); 
         wday2=(max_day1-(7-wday1))%7; 
                //输出月英文名字 
                m_len=strlen(month_name_en[i]); 
                left=(27-m_len)/2+m_len; 
                printf("%*s",left,month_name_en[i]); 
                //剩下的位置用空格补齐 
                for(j=0;j<27-left;j++) 
                  printf(" "); 
                //输出4个空格作为间隔 
                for(j=0;j<4;j++) 
                  printf(" "); 
          //输出横排第二个月的名字           
           m_len=strlen(month_name_en[i+1]); 
           left=(27-m_len)/2+m_len; 
           printf("%*s\n",left,month_name_en[i+1]); 
 
           //开始输出星期的英文名字 
           printf("%s",week_name_en[0]); 
           for(j=1;j<7;j++) 
           { 
                     printf("%4s",week_name_en[j]); 
           } 
           for(j=0;j<4;j++) 
             printf(" "); 
                      printf("%s",week_name_en[0]); 
           for(j=1;j<7;j++) 
           { 
                     printf("%4s",week_name_en[j]); 
           } 
           printf("\n");   
           //星期的英文名字输出完毕 
           //开始输出当前月的日期 
           //一行一行的输出,同时输出两个月的 
           //每个月的日期是一个6*7的方形矩阵  
 
           //先输出第一个行, 
 
             if(i!=0){ 
               gday2=gday1+max_day1; 
             } 
             else 
               gday2=1+max_day1; 
             //输出站位空字符  
         for(w=0;w<wday1;w++) 
         { 
                   if(w==0) 
                     printf("%3s"," "); 
                   else 
                     printf("%4s"," "); 
         } 
         //输出日期 
         for(;w<7;w++) 
         { 
                 if(w==0){ 
                     printf("%3d",fmt?gday1:day1); 
                  } 
                  else{ 
                     printf("%4d",fmt?gday1:day1); 
                   } 
                   day1++; 
                   gday1++; 
         } 
         //第一个月的第一行输出完毕 
         //输出4个空格作为间隔 
         printf("%4s"," "); 
             //输出第二个月的第一行 
             //此处应该可以根据上一个月算出从第几个开始 
 
                   //输出站位空字符  
            for(w=0;w<wday2;w++) 
         { 
                   if(w==0) 
                     printf("%3s"," "); 
                   else 
                     printf("%4s"," "); 
         }   
             //输出日期 
 
         for(;w<7;w++) 
         { 
                 if(w==0){ 
                     printf("%3d",fmt?gday2:day2); 
                  } 
                  else{ 
                     printf("%4d",fmt?gday2:day2); 
                   } 
                   day2++; 
                   gday2++; 
         } 
           printf("\n"); 
           //开始下面的输出 
           for(j=1;j<6;j++) 
           { 
                   //第一个矩阵 
         //开始输出日期 
          for(w=0;w<7;w++) 
          { 
                  if(day1<=max_day1) 
                  { 
                          if(w==0){ 
                             printf("%3d",fmt?gday1:day1); 
                          } 
                          else{ 
                             printf("%4d",fmt?gday1:day1); 
                           } 
                           day1++; 
                           gday1++; 
                  }else{ 
                           if(w==0) 
                       printf("%3s"," "); 
                       else 
                       printf("%4s"," ");         
                  } 
          } 
             printf("%4s"," ");     
 
                //第二个矩阵  
              //gday2=gday1+max_day1; 
          for(w=0;w<7;w++) 
          { 
                  if(day2<=max_day2) 
                  { 
                    if(w==0) 
                      printf("%3d",fmt?gday2:day2); 
                     else 
                       printf("%4d",fmt?gday2:day2); 
                           day2++; 
                           gday2++; 
                  }else{ 
 
                           if(w==0) 
                       printf("%3s"," "); 
                       else 
                       printf("%4s"," ");         
                  } 
          } 
          printf("\n"); 
           } 
                   gday1=gday2; 
                   wday1=(max_day1-(7-wday2)) % 7; 
        } 
        printf("\n"); 
} 
 
void printMonthOnYearCal(PDate date,int fmt){ 
        int i; 
        int m_len; 
        int day; 
        int max_day; 
        int p=1; 
        max_day=monthMaxDay(date->tm_year,date->tm_mon); 
        printf("%*s %d %s\n",(27-(m_len=strlen(month_name_en[date->tm_mon])))/2+m_len-4,month_name_en[date->tm_mon],date->tm_year+1900,animals[((date->tm_year+1900)-4)%12]); 
        printf(week_name_en[0]); 
        for(i=1;i<7;i++) 
        { 
           printf("%*s",4,week_name_en[i]);         
        } 
        printf("\n"); 
        for(i=0;i<date->tm_wday;i++) 
        { 
          if(i==0) 
            printf("%*s",3," "); 
          else 
             printf("%*s",4," "); 
        } 
         day=1;  
         if(fmt==1) 
            day=date->tm_yday+1; 
        for(;i<7;i++){ 
                if(i==0) 
              printf("%*d",3,day++); 
            else 
              printf("%*d",4,day++); 
          if(i==6){ 
             i=-1;  
               printf("\n"); 
          } 
          if(p++>=max_day) 
            break; 
        } 
        printf("\n");  
 
} 
int main(int argc,char *argv[]){ 
        int y; 
        int m; 
        int fmt; 
        fmt=0; 
        y=-1; 
        m=-1; 
        time_t c_tm; 
        time_t c_tm2; 
 
        PDate pdate; 
        PDate pdate2; 
        int i; 
        for(i=1;i<argc;) 
        { 
           if(!strcmp(argv[i],"-m")&&(i+1<argc)) 
           { 
                     m=atoi(argv[i+1])-1; 
                     if(m<0||m>11) 
                     { 
                                     printf("month  range (1~12)\n"); 
                                     printf("-h    help info.\n"); 
                                     exit(0); 
                                     return 0; 
                     } 
                     i+=2; 
           }         
           else if(!strcmp(argv[i],"-y") && (i+1<argc)){ 
                     y = atoi(argv[i+1])-1900; 
                     if(y<=0) 
                     { 
                                     printf("year range (>1900)\n"); 
                                printf("-h    help info.\n"); 
                                     exit(0); 
                                     return 0; 
                     } 
                     i+=2; 
           }else if(!strcmp(argv[i],"-j")) 
           { 
                     i++; 
                     fmt=1; 
           }else if(!strcmp(argv[i],"-h")) 
           { 
                       printHelp(); 
                       exit(0); 
                       return 0; 
           }else { 
                       printHelp(); 
                       exit(0); 
                       return 0; 
           } 
        } 
        time(&c_tm); 
        pdate=localtime(&c_tm); 
        if(m==-1) 
        { 
                if(y>0) 
                { 
                        pdate->tm_year=y; 
                        printYearCal(pdate,fmt);                 
                }else{ 
                          printMonthOnYearCal(pdate,fmt); 
                } 
        }else{ 
                if(y>0) 
                { 
                        pdate->tm_year=y; 
                        pdate->tm_mon=m; 
                        pdate->tm_mday=1; 
                        c_tm2=mktime(pdate); 
                        if(c_tm2==-1) 
                         { 
                           printf("can't mktime . \n"); 
                           printf("-h    help info.\n"); 
                            exit(0); 
                            return 0;         
                         } 
                        pdate2=localtime(&c_tm2); 
                        printMonthOnYearCal(pdate2,fmt);                 
                }else{ 
                           printMonthOnYearCal(pdate,fmt); 
                }         
        } 
  return 0;         
}

update:
增加了一个小功能,可以在控制台输出带颜色的字体。
引用windows.h文件调用里面的

  HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); 
   if(h) 
         SetConsoleTextAttribute(h,color);

可以达到效果,只更新了-h,及月视图的颜色,如果年视图带颜色感觉有点乱了:)