我想 grep 特定错误消息周围的日志块。假设我知道我的日志如下所示:
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004] INFO -- : Started GET "/ems_infra/new" for 4.2.2.2 at 2014-04-10 15:12:36 -0400
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004] INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
我对整个区块都很感兴趣。有没有办法让我的 grep 以错误为中心FATAL
,并抓取到Started GET
和 到Completed 200 OK
?
我知道这grep -B 123 -A 456 "FATAL" file.txt
可以解决问题,但这需要我提前知道FATAL
第一行(123)和最后一行(456)之间的距离[1]。
答案1
恐怕 grep 没有这样的功能。perl 和/或 python 可能有。我一时兴起(没有花太多心思)就想出了以下 awk 组合。
awk '/Started GET/{print ""};1' blurble | awk 'BEGIN{RS=ORS="\n\n";FS=OFS="\n"}/FATAL/{print $0}'
给定一个从你的代码片段(x4)中编造的日志块和一些额外的“其他日志”行以及两个“FATAL”行被删除,我得到了两个打印段:
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004] INFO -- : Started GET "/ems_infra/new" for 4.2.2.2 at 2014-04-10 15:12:36 -0400
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004] INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004] INFO -- : Started GET "/ems_infra/new" for 4.2.2.2 at 2014-04-10 15:12:36 -0400
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004] INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004] INFO -- : Started GET "/ems_infra/new" for 4.2.2.2 at 2014-04-10 15:12:36 -0400
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004] INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004] INFO -- : Started GET "/ems_infra/new" for 4.2.2.2 at 2014-04-10 15:12:36 -0400
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004] INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
对该文件(我称之为 blurble)运行两个 awk 会得到以下输出:
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004] INFO -- : Started GET "/ems_infra/new" for 4.2.2.2 at 2014-04-10 15:12:36 -0400
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004] INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004] INFO -- : Started GET "/ems_infra/new" for 4.2.2.2 at 2014-04-10 15:12:36 -0400
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004] INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004] INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
答案2
我有一个可能有帮助的脚本:https://github.com/jakl/blocks
./blocks.pl --delim '开始 GET|完成 200 OK' --term 'FATAL'
它将日志分成以 --delim 开头或结尾的块,并打印包含 --term 的块
答案3
这是使用 sed 的一行代码
sed -n '/Started/,/Completed/H;/Completed/{z;x;/FATAL/p}' log
一行代码展开解释
# do not print lines unless explicitly told to do so
sed -n '
# put everything between Started and Completed in hold space
/Started/,/Completed/ H;
# if at Completed
/Completed/ {
# empty the pattern space
z;
# switch hold space with pattern space
x;
# if FATAL in pattern space then print
/FATAL/p
}
' log
请注意,这将在每个块之间打印一个空行。空行来自组合z;x;
。z
清空模式空间。x
将保持空间与模式空间切换。这意味着z;x;
在保持空间中有一个空行。如果在与保持空间切换之前没有清空模式空间,则下一个块中将出现前一个块的最后一行。我试图解决这个问题以防止出现空行,但这使代码变得更加复杂。
如果空行让您感到困扰,您可以将其过滤掉...使用另一个 sed 命令。
sed -n '/Started/,/Completed/H;/Completed/{z;x;/FATAL/p}' log | sed '/^$/d'
或者你可以放置一个标记,使该命令的输出几乎像 grep
sed -n '/Started/,/Completed/H;/Completed/{z;x;/FATAL/p}' log | sed 's/^$/--/'
这是我想出的最简单的解决方案,可以消除空行
sed -n '
# replace hold space with pattern space
/Started/ h
/Started/,/Completed/ {
# skip the first line because it is already in hold space
/Started/ n
# append pattern space to hold space
H
}
/Completed/ {
# switch hold space with pattern space
x
# if FATAL in pattern space then print
/FATAL/ p
}
' log
与强制性的一行相同
sed -n '/Started/h;/Started/,/Completed/{/Started/n;H};/Completed/{x;/FATAL/p}' log