使用unix命令在日志文件中区分时间戳

时间:2011-09-19 03:23:45

标签: unix timestamp logfiles

我有一个包含这样的行的日志文件:

...timestamp...(id=1234)..GO...
...timestamp...(id=1234)..DONE...

事实:

  • 时间戳的格式为HH:MM:SS.ssss(s为部分秒数)
  • 每个'id'号码都有两个相关的行,一个是“GO”和一个“DONE”
  • 两条相关的线不一定是彼此相邻的;该文件是按时间顺序排列的

我想要的是什么:

  • 匹配关联的GO / DONE线
  • 区分时间戳
  • (理想情况下)创建一个以下格式的新文件:

    diffTime <GO line> <DONE line>
    

我的主要观点是区分时间戳。这将非常有用,我缺乏编写它的sort / sed / awk技能。是否有日志文件工具来帮助解决这种黑客问题?

2 个答案:

答案 0 :(得分:3)

我不知道任何这样的工具,但可以在shell中编写它。例如,此日志:

11:18:51 (id=123) GO
11:18:52 (id=124) GO
11:18:53 (id=123) DONE
11:18:54 (id=125) GO
11:18:55 (id=125) DONE
11:18:55 (id=124) DONE

可以转换为

2 123
3 124
1 125

第一列是以秒为单位的时间,第二列是事务ID。

命令是:

cat example.log
| sed 's|\([^ ]\+\) (id=\([^)]\+\)) \(.\+\)|\1 \2 \3|;s|GO|1|;s|DONE|2|'
| sort -k2,3
| paste - -
| tr ':' ' '
| awk '{printf("%d %d\n", ((($6-$1)*60*60)+(($7-$2)*60)+($8-$3)), $4)}'

这种单行程可能会更加简化。

工作原理:

  • 将行格式更改为“11:18:51 123 GO”
  • 将GO替换为1,将DONE替换为2(因为稍后它允许我们对其进行正确排序)
  • 按交易ID和状态
  • 对结果行进行排序
  • 加入每两行(现在每个结果行描述事务的开始和结束)
  • 将所有冒号替换为空格(以便稍后简化awk次尝试)
  • 通过手动分割来计算时间差异
  • 打印结果

答案 1 :(得分:2)

这是一个让你半途而废的脚本:

#!/bin/bash

# Script must be called with one parameter, the name of the file to process
if [ $# -ne 1 ]; then
  echo "Usage: $0 filename"
  exit
fi

filename=$1


# Use sed to put the timestamp after the id
#    10:46:01:0000 (id=20) GO
#    10:46:02:0000 (id=10) GO
#    10:46:03:0000 (id=10) DONE
#    10:46:04:0000 (id=20) DONE
#
#  becomes
#
#    (id=20) 10:46:01:0000 GO
#    (id=10) 10:46:02:0000 GO
#    (id=10) 10:46:03:0000 DONE
#    (id=20) 10:46:04:0000 DONE
#
# \1 timestamp
# \2 id
# \3 status (GO or DONE)
#         \1          \2              \3
sed -e "s/\([0-9:]*\) \((id=[0-9]*)\) \(.*\)/\2 \1 \3/" $filename > temp1


# Now sort the file. This will cause timestamps to be sorted, grouped by id
#    (id=20) 10:46:01:0000 GO
#    (id=10) 10:46:02:0000 GO
#    (id=10) 10:46:03:0000 DONE
#    (id=20) 10:46:04:0000 DONE
#
#  becomes
#
#    (id=10) 10:46:02:0000 GO
#    (id=10) 10:46:03:0000 DONE
#    (id=20) 10:46:01:0000 GO
#    (id=20) 10:46:04:0000 DONE
sort temp1 > temp2


# Use sed to put the id after the timestamp
#    (id=10) 10:46:02:0000 GO
#    (id=10) 10:46:03:0000 DONE
#    (id=20) 10:46:01:0000 GO
#    (id=20) 10:46:04:0000 DONE
#
#  becomes
#
#    10:46:02:0000 (id=10) GO
#    10:46:03:0000 (id=10) DONE
#    10:46:01:0000 (id=20) GO
#    10:46:04:0000 (id=20) DONE
# \1 id
# \2 timestamp
# \3 status (GO or DONE)
sed -e "s/\((id=[0-9]*)\) \([0-9:]*\) \(.*\)/\2 \1 \3/" temp2 > temp3

其余的...在运行此脚本之后,每个GO行后面都会跟一个具有相同id的DONE行,假设存在这样的DONE行。

接下来,您可以读取每对行,提取时间戳并区分它们(查看Johnsyweb建议的时间戳函数)。然后将两条线合并为一条线。您的结果现在看起来像:

#    1s 10:46:02:0000 (id=10) GO 10:46:03:0000 (id=10) DONE
#    3s 10:46:01:0000 (id=20) GO 10:46:04:0000 (id=20) DONE

注意起始时间戳的条目是如何乱序的。这是因为我们之前按id排序。我将把它作为练习让你弄清楚如何以正确的顺序获得条目。我们希望id = 20的条目在id = 10之前,因为id = 20是在id = 10之前启动的。

#    3s 10:46:01:0000 (id=20) GO 10:46:04:0000 (id=20) DONE
#    1s 10:46:02:0000 (id=10) GO 10:46:03:0000 (id=10) DONE

我确定这很令人困惑,所以如果您有疑问,请告诉我。我确信有更有效的方法可以做到这一切,但这就是我想到的。