现在是晚上10点,我还在单位里面,为什么会这么晚呢,因为自己太弱了!!4月10号凌晨一台机器Machine Restart,祸不单行,重启以后由于NTP服务也down 掉了,搞得系统时间比正确时间快了1个小时。由于我们在这台机器上面部署的Application运行的时候都依赖于系统时间,搞得应用进程跳过当前时间,不停的试图处理将来的数据。为了恢复这个问题,需要找到系统时间出错前应用进程的所有任务的时间戳,然后从那些时间戳replay所有任务。
关于以上4点的说明:
早上看到这个问题的时候,我就回了一下说Hi Guys, I will look into this issue。Edward说Todd有一个脚本可以完成这个工作的,找到Todd,Todd找不到以前的脚本了,而且他很忙,我只能自己干了。呀呀的,早知道前些日子把Perl学学好了,而且我Unix的Shell也不熟。后来我们想象,还是有一些地方是要注意的。
什么是任务的时间戳,就是任务的步骤1的时间戳,可是标志步骤的log上面并没有任务的名字,所以只能用线程ID来标识。
my $block = `grep Task1 logfile.log | head -1`; #找到Task启动的那一行,那里有Task1对应的线程ID
$block=~/[(TID:.*)]/; #得到表示Task1的线程ID,保存在$1中
$block = `grep ‘$1′ logfile.log | grep Step1 | tail -1`; #找到任务最后一次执行Step1的时间
$block=~/((d+))$/; #得到时间戳,保存在$1中
对吗,对吗??错啦!!错啦!!为什么呀?
那好,如果把找寻Task1的线程ID的代码这样改一下呢:
my $block = `grep Task1 logfile.log | tail -1`; 我们拿最后一个匹配的Task1的记录,还是错啦,因为我们的问题是要找到问题发生前的所有任务的时间戳,不是从当前时间往前找寻所有任务的时间戳啊。系统时间被篡改是4月10号临晨00:56分。所有被VCS在00:56分以后漂移到该物理节点的应用进程都会受到影响。每次漂移应用进程都会重新启动的。所以正确的做法是先要找到4月临晨00:56分以后应用进程第一次启动的log,假设该事件点是T,从那个点往前找Task1启动的记录,找到线程ID,再用那个线程ID再次从T往前找Step1的时间戳!
my $timestamp="Thu Apr 10 00:56:00 2008";
my $logfile = "logfile.log";
my $linescan=500; #向"过去"扫描的行数
my $line = ` grep -n "$timestamp" $logfile| grep ‘Process Started’ | tail -1`;
$line =~/^(d+):/; #找到系统出问题之后应用进程第一次启动的地点
$my linenum=$1;
my $block = `head -$linenum $logfile | tail -$linescan | grep Task1| head -1`;
$block=~/[(TID:.*)]/;
$block = `head -$linenum $logfile | tail -$linescan | grep ‘$1′ | grep Step1 | tail -1`;
$block=~/((d+))$/;
print "Task1::Step1 : ",$1,"n"; #打印时间戳
*********************************************************************************
一共就几行代码啊,搞了我好几个小时!真TMD衰。而且这个脚本用起来一点也不爽,因为我们有很多很多的任务,还有很多很多的log文件,后来Todd写了一个自动化程度比较高的脚本,可以自动找到所有的log文件,然后打印所有的问题出现前的时间戳,并且生成应用进程可以直接读的文件。