免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5051 | 回复: 10
打印 上一主题 下一主题

求助:aix中,能否自动将crontab作业前天出错的日志保存到另一个文本中 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-09-06 22:54 |只看该作者 |倒序浏览
本帖最后由 bzbenjoy 于 2011-09-07 21:41 编辑

在aix中,/var/adm/cron/log记录了crontab的执行情况,log格式如下:
  1. ............
  2. oracle2   : CMD ( /u33/admin/autofree.sh  ) : PID ( 229730 ) : Tue Sep  5 15:23:00 2011
  3. Cron Job with pid: 229730 Successful
  4. root      : CMD ( /usr/run_ssa_encl_healthcheck) : PID ( 327904 ) : Tue Sep  5 15:30:00 2011
  5. root      : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Tue Sep  5 15:30:00 2011
  6. Cron Job with pid: 327904 Successful
  7. Cron Job with pid: 303494 Failed
  8. oracle2   : CMD ( /u33/admin/bkarch.sh ) : PID ( 606448 ) : Tue Sep  6 15:31:00 2011
  9. Cron Job with pid: 606448 Successful
  10. oracle2   : CMD ( /u33/admin/autofree.sh ) : PID ( 512120 ) : Tue Sep 6 15:33:00 2011
  11. Cron Job with pid: 512120 Successful
  12. ............
复制代码
现在我想通过一个脚本文件,每次执行的时候,能够找出相对于系统时间前一天,crontab出错的行数,然后保存到另一个文本,
大概像这样子:
  1. ..........
  2. root      : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Tue Sep  5 15:30:00 2011
  3. Cron Job with pid: 303494 Failed
  4. ..........
复制代码
要用awk找出failed那行很简单,但是,怎么将failed所对应的那命令行(就是有cmd命令,执行时间的那行)也找出来,这个很头痛,比如说上面这个例子,awk执行完上面的root那行后,才会读取303494的这行,发现failed后,没法再回退到前一行(或几行,因为有些作业执行时间比较久,两条记录中间可能会有间隔)找到相同PID的那行,打印出来啊,就算把保存一个和log相同内容的文本,2个文本来比较,也很难实现
      还有,截取前一天的记录,比如,现在系统时间是2011年9月6号,截取2011年9月5号的记录(文本中Tue Sep 的那些行),这个怎么处理,第一点,时间怎么匹配,还有,由于关键字在每行的倒数几个域(倒3个域到倒数5个域),但是,从上面root行可以看出来,由于CMD夸号里面的命令长短都不一样,因此,虽然awk可跟踪域的个数,但是域长度不定的话,怎么定位到需要的那几个域啊?
      有没有高手感兴趣的,能否提供点建议,想这个想好久了,还是没能想出来该怎么实现,或者,能用别的方式也好,只要能达到效果也行啊

****************************************************************************************************************************************************************************************************************

补充:
       非常感谢jason680大大和yinyuemi,我今天试了一下,strftime的确不支持strftime,date -d倒是没有试过
      还有,我昨天没有说清楚,cmd夸号里面的命令长度不一样,是指有可能多了重定向之类的,这样的话就不好定位时间和PID序列号是在哪一个域,比如:
  1. root      : CMD ( /usr/lpp/diagnostics/bin/run_ssa_encl_healthcheck 1>/dev/null 2>/dev/null ) : PID ( 1700156 ) : Tue Sep  6 20:30:00 2011
复制代码
这个的话,两位大大的方法就有点不适用
      根据两位大大的思路,我写了下面的方法来尝试:
  1. awk -v var=`date "+%a"`   -v Rec=100 'BEGIN{a["Mon"]="Sun";a["Tue"]="Mon";a["Wed"]="Tue";a["Thu"]="Wed";a["Fri"]="Thu";a["Sat"]="Fri";a["Sun"]="Sat"}
  2. {if ($6=="Failed"){n=(n+1)%Rec;b[n]=$5;m[n]=$0}}
  3. {if($0 ~a[var])
  4.                          {for(n=0;n<Rec;n++)if($0 ~b[n])
  5.                                                 {print $0"\n"m[n]}
  6.                         }
  7. }' log
复制代码
不过,执行后,发现$0,然后空行,然后$0,然后空行,重复了一百遍(还是99遍?现在有点忘了),然后在输出下一条出错的$0,比如这样一种重复
  1. root      : CMD ( /mapsdata/mapsp/adm/perf.sh ) : PID ( 1765822 ) : Tue Sep  6 20:10:00 2011

  2. root      : CMD ( /mapsdata/mapsp/adm/perf.sh ) : PID ( 1765822 ) : Tue Sep  6 20:10:00 2011

  3. root      : CMD ( /mapsdata/mapsp/adm/perf.sh ) : PID ( 1765822 ) : Tue Sep  6 20:10:00 2011

  4. root      : CMD ( /mapsdata/mapsp/adm/perf.sh ) : PID ( 1765822 ) : Tue Sep  6 20:10:00 2011
复制代码
把参数 Rec=2和最后的输出print $0"\n"m[n]换成print $0的话,倒是可以输出全部出错的$0,如:
  1. root      : CMD ( /mapsdata/mapsp/adm/perf.sh ) : PID ( 1765822 ) : Tue Sep  6 20:10:00 2011
  2. root      : CMD ( /mapsdata/mapsp/adm/autokill.sh 1>>/mapsdata/mapsp/tmp/autokill.log 2>>/mapsdata/mapsp/tmp/autokill.log ) : PID ( 1765832 ) : Tue Sep  6 20:13:00 2011
复制代码
只是这样的话,就缺了Failed那行,到底是为什么? 还有,有解决的办法吗?

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
2 [报告]
发表于 2011-09-07 00:01 |只看该作者
在aix中,/var/adm/cron/log记录了crontab的执行情况,log格式如下:
............
oracle2   : CMD ( /u ...
bzbenjoy 发表于 2011-09-06 22:54



Rec是用来保留Failed时..往前找几项CMD用...
$ awk -F'[ )]+' -v Rec=100 'BEGIN{d1=strftime("%b %e",systime()-24*3600)}{if($2=="CMD"{n=(n+1)%Rec;a[n]=$5;m[n]=$0;d[n]=sprintf("%s %2d",$7,$}if($6=="Failed"{for(n=0;n<Rec;n++)if(a[n]==$5&&d1==d[n]){print m[n]"\n"$0}}}' log
root      : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Tue Sep  5 15:30:00 2011
Cron Job with pid: 303494 Failed

* d1是用产生前一天日期...(Sep 5)
   Sep 5 应该是Mon,但你的log是Tue就不检查了
* 找到CMD时($2=="CMD"
   用PID号码($5),保留全部(m[n]=$0)及日期(d[n]=sp...,$7,$
* 找到Failed时($6=="Failed"....
   由刚保留记录中,找出相对的PID(a[n]==$5) ,日期为前一天 d1==d[n]

论坛徽章:
2
射手座
日期:2014-10-10 15:59:4715-16赛季CBA联赛之上海
日期:2016-03-03 10:27:14
3 [报告]
发表于 2011-09-07 00:04 |只看该作者
本帖最后由 yinyuemi 于 2011-09-07 01:25 编辑

回复 1# bzbenjoy
  1. echo 'oracle2   : CMD ( /u33/admin/autofree.sh  ) : PID ( 229730 ) : Tue Sep  5 15:23:00 2011
  2. Cron Job with pid: 229730 Successful
  3. root      : CMD ( /usr/run_ssa_encl_healthcheck) : PID ( 327904 ) : Tue Sep  5 15:30:00 2011
  4. root      : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Tue Sep  5 15:30:00 2011
  5. Cron Job with pid: 327904 Successful
  6. Cron Job with pid: 303494 Failed
  7. oracle2   : CMD ( /u33/admin/bkarch.sh ) : PID ( 606448 ) : Tue Sep  6 15:31:00 2011
  8. Cron Job with pid: 606448 Successful
  9. oracle2   : CMD ( /u33/admin/autofree.sh ) : PID ( 512120 ) : Tue Sep 6 15:33:00 2011
  10. Cron Job with pid: 512120 Successful' |\
  11. awk -v var="$(date -d yesterday +"%b  %d"|sed 's/0//')" -v RS="root"  -v FS="\n" '$1~var{for(i=2;i<=NF;i++)if($i~/Failed/)t=t ORS $i;printf t?"root" $1 t ORS:""}'

  12. root      : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Tue Sep  5 15:30:00 2011
  13. Cron Job with pid: 303494 Failed
复制代码
aix环境可能不支持date -d,见4#

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
4 [报告]
发表于 2011-09-07 00:26 |只看该作者
回复  bzbenjoy
yinyuemi 发表于 2011-09-07 00:04


yinyuemi大..
awk -v var="$(date -d yesterday +"%b  %d"|sed 's/0//')"
1. 你太依赖外在命令,不知lz的aix,有没有支持date -d ....
2. s/0// 有可能把 Sep 10 ==> Sep 1

论坛徽章:
2
射手座
日期:2014-10-10 15:59:4715-16赛季CBA联赛之上海
日期:2016-03-03 10:27:14
5 [报告]
发表于 2011-09-07 00:47 |只看该作者
本帖最后由 yinyuemi 于 2011-09-07 01:25 编辑

回复 4# jason680


    谢谢提醒,没注意lz的运行环境是AIX,应该不支持date -d
    你代码中的strftime是GNU扩展的,nawk可能也不支持。
    我从星期上考虑的,不知是否可行?代码如下:
  1. echo 'oracle2   : CMD ( /u33/admin/autofree.sh  ) : PID ( 229730 ) : Mon Sep  5 15:23:00 2011
  2. Cron Job with pid: 229730 Successful
  3. root      : CMD ( /usr/run_ssa_encl_healthcheck) : PID ( 327904 ) : Mon Sep  5 15:30:00 2011
  4. root      : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Mon Sep  5 15:30:00 2011
  5. Cron Job with pid: 327904 Successful
  6. Cron Job with pid: 303494 Failed
  7. oracle2   : CMD ( /u33/admin/bkarch.sh ) : PID ( 606448 ) : Tue Sep  6 15:31:00 2011
  8. Cron Job with pid: 606448 Successful
  9. oracle2   : CMD ( /u33/admin/autofree.sh ) : PID ( 512120 ) : Tue Sep 6 15:33:00 2011
  10. Cron Job with pid: 512120 Successful' |\
  11. awk -v var="$(date "+%a")" -v RS="[^\n]+: CMD"  -v FS="\n" 'BEGIN{a["Mon"]="Sun";a["Tue"]="Mon";a["Wed"]="Tue";a["Thu"]="Wed";a["Fri"]="Thu";a["Sat"]="Fri";a["Sun"]="Sat"}{b[NR+1]=RT}$1~": "a[var]{for(i=2;i<=NF;i++)if($i~/Failed/)t=t ORS $i;printf t?b[NR] $1 t ORS:"";t=""}'
  12. root      : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Mon Sep  5 15:30:00 2011
  13. Cron Job with pid: 303494 Failed
复制代码

论坛徽章:
0
6 [报告]
发表于 2011-09-07 20:54 |只看该作者
回复 2# jason680


  jason680大大,您好,你给我的建议中,Rec=100,n=(n+1)%Rec是用来做什么的? 能稍微解释一下吗?

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
7 [报告]
发表于 2011-09-08 09:09 |只看该作者
本帖最后由 jason680 于 2011-09-08 09:10 编辑
回复  jason680


  jason680大大,您好,你给我的建议中,Rec=100,n=(n+1)%Rec是用来做什么的? 能稍 ...
bzbenjoy 发表于 2011-09-07 20:54


基本上Rec它是用来限制数组大小用的....
因为一般log纪录,可能会很多....
就如你说,当你找到pid: xxxx Failed时,前面CMD的纪录已经过了....
root : CMD ( /usr/run_ssa_encl_healthcheck) : PID ( 327904 ) : Tue Sep 5 15:30:00 2011
root : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Tue Sep 5 15:30:00 2011
Cron Job with pid: 327904 Successful
Cron Job with pid: 303494 Failed

一般我们使用的方法,就是先把CMD存下来(放在数组中)
但在log中CMD的纪录有可能很多,会影响效率....
所以我想到的方法就是限制数组大小

Rec=100
n =(n+1)%Rec
n为0时, 执行结果 n=1
n为1时, 执行结果 n=2
...
n为98时, 执行结果 n=99
n为99时, 执行结果 n=0
n为99, n+1为100, 因为多了%Rec (等同%100),
结果n又为0,纪录又从头开始.

刚刚在写说明时发现,这可能有个bug(但也有可能没问题)

root : CMD ( /u33/admin/check_xxxxx.sh) : PID ( 303494 ) : Mon Sep 5 13:30:00 2011
Cron Job with pid: 303494 Successful
....
root : CMD ( /usr/run_ssa_encl_healthcheck) : PID ( 327904 ) : Mon Sep 5 15:30:00 2011
root : CMD ( /u33/admin/check_icmrm.sh ) : PID ( 303494 ) : Mon Sep 5 15:30:00 2011
Cron Job with pid: 327904 Successful
Cron Job with pid: 303494 Failed
  
303494 Failed有可能会匹配到,前面的纪录.(但这只有在PID会相同的情形下)

==================================================
另外一个不比较不影响效率,也不用限制CMD纪录数组​​的方法,又不会有以上bug的方法.
就是今天是Sep 6时,先算出前一天(Sep 5)日期,仍后在纪录CMD时,先检查是否为Sep 5
if($2=="CMD"
改为if($2=="CMD" && d1==sprintf("%s %2d",$7,$ )
这样后面就不须要限制数组大小(因为前一天的CMD纪录,就会比较少了),直接
  a[$5] = $0 # $5 为PID号码,不必限制数组大小,且PID重复时,后一个会盖过前一个
最后
  if($6=="Failed"&&a[$5]!=""){print a[$5]"\n"$0}
  else{print "cannot find the PID record in CMD"}

论坛徽章:
15
2015年辞旧岁徽章
日期:2015-03-03 16:54:15双鱼座
日期:2015-01-15 17:29:44午马
日期:2015-01-06 17:06:51子鼠
日期:2014-11-24 10:11:13寅虎
日期:2014-08-18 07:10:55酉鸡
日期:2014-04-02 12:24:51双子座
日期:2014-04-02 12:19:44天秤座
日期:2014-03-17 11:43:36亥猪
日期:2014-03-13 08:13:51未羊
日期:2014-03-11 12:42:03白羊座
日期:2013-11-20 10:15:18CU大牛徽章
日期:2013-04-17 11:48:45
8 [报告]
发表于 2011-09-08 09:35 |只看该作者
  1. YESTERDAY=$(TZ=aaa24 date +"%b %e")

  2. awk -v d="$YESTERDAY" '/^Cron Job/&&/Failed/&&a[$5]~d{print a[$5] RS $0;next}
  3.           {a[$10]=$0}' infile.log
复制代码

论坛徽章:
0
9 [报告]
发表于 2011-09-08 22:11 |只看该作者
本帖最后由 bzbenjoy 于 2011-09-08 22:22 编辑

回复 7# jason680


    多谢,终于搞懂了你的代码的意思,又学会了点东西,我后来想了下,根据你们和另几个大大的的思路,也想出来了一种方法,只是这方法时间的问题解决的还不是很好
  1. today=`date "+%b %e %Y"`
  2. yesterday=`TZ=aaa16 date "+%b %e %Y"`

  3. awk -F'[ :()]+' '
  4.                 BEGIN{flag=0;n=0}
  5.                 {     if($2=="CMD"){if($0 ~today||$0 ~yesterday){n=n+1;flag=1;a[n]=$0;continue;}}
  6.                        if(flag==1 && $1=="Cron"){for(i=1;i<=n;i++)
  7.                                                {if(index(a[i],$5)){  if(index($0,"Failed")){print a[i];print $0;}
  8.                                                                                         n=n-1;
  9.                                                                                         for(j=i;j<=n;j++)
  10.                                                                                              {a[j]=a[j+1];}
  11.                                                                                         break;
  12.                                                                                                  }}}
  13.                }
  14. 'log
复制代码
只是这个方法,时间取得不是很精确,log日志里面时间跨度比较长的话,就很糟糕,还没想好要怎么解决

论坛徽章:
0
10 [报告]
发表于 2011-09-08 22:13 |只看该作者
本帖最后由 bzbenjoy 于 2011-09-08 22:17 编辑

回复 8# rdcwayx


    请帮忙看看,这个awk代码:
  1. today=`date "+%b %e %Y"`
  2. yesterday=`TZ=aaa16 date "+%b %e %Y"`

  3. awk -F'[ :()]+' '
  4.                 BEGIN{flag=0;n=0}
  5.                 {     if($2=="CMD"){if($0 ~today||$0 ~yesterday){n=n+1;flag=1;a[n]=$0;continue;}}
  6.                        if(flag==1 && $1=="Cron"){for(i=1;i<=n;i++)
  7.                                                                 {if(index(a[i],$5)){  if(index($0,"Failed")){print a[i];print $0;}
  8.                                                                                                 n=n-1;
  9.                                                                                                 for(j=i;j<=n;j++)
  10.                                                                                                 {a[j]=a[j+1];}
  11.                                                                                                 break;
  12.                                                                                                         }}}
  13.                }
  14. 'log
复制代码
里面,为什么第六行的if($0 ~today||$0 ~yesterday)没有生效,我执行这个命令,发现所有的行都直接通过,没有进行筛选?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP