如何使用awk或grep在日志文件中捕获整个Python回溯?

时间:2013-07-09 22:33:02

标签: python logging awk grep

日志文件包含许多Python回溯。我只关心由KevinCustomError引发的追溯。文件中可能存在多个此类错误。

如何使用grep,另一个流行的unix命令或其组合来转储我的特定错误的整个回溯?

这是一个示例日志文件。我想从这个文件中的第1-3行。在真实的日志文件中,回溯要长得多。

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
KevinCustomError: integer division or modulo by zero
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ZeroDivisionError: integer division or modulo by zero

4 个答案:

答案 0 :(得分:1)

如果我正确理解了Python日志文件的结构,则以下是一个很小的sed解决方案,它的神秘性比看上去要低

#!/usr/bin/sed -f
/^Traceback/{
:here
N
/\nKevinCustomError/b
s/.*\n\(Traceback\)/\1/
b here
}

总结,该脚本仅对以Traceback开头的行执行操作;在这些行上,脚本会继续添加新行(N),并随后检查新添加的行是否以KevinCustomError开始;如果是这种情况,脚本将分支到最后并打印多行图案空间;如果不是,那么脚本将从模式空间中除去最后一行Traceback以外的所有内容,然后分支回到:here并追加另一行(N),依此类推。 / p>

详细信息如下:

  1. #!/usr/bin/sed -f:这是shebang行,它告诉Shell使用/usr/bin/sed作为解释器,并通过-f选项将file参数传递给它(这允许执行./script file而不是sed -f script file);
  2. /^Traceback/仅匹配以Traceback开头的行;
  3. {…}将仅对那些在步骤2中匹配的行执行的命令进行分组;
    1. :here不是命令,而只是一个标签,它通过t est或b ranch命令标记了我们可以返回的行;
    2. N读取并在当前模式空间后面添加以下文本行,并在其之间插入换行符\n,从而使模式空间成为多行;
    3. /\nKevinCustomError/b,如果模式空间包含b后跟KevinCustomError,则此\n到脚本末尾;
      • 这导致p删除多行图案空间,该空间以Traceback开头,其中包含(至少)一个\n,并且包含{ {1}}(最后一个)KevinCustomError之后;
    4. \n(如果3.中的模式不匹配,我们就在这里)删除模式空间的前导部分,直到最后一个s/.*\n\(Traceback\)/\1/;包括最后一个\n
    5. b here分支到:here,并且此时没有打印。

答案 1 :(得分:0)

这是我试图鞭打的AWK脚本。

awk '{a[NR]=$0}; /KevinCustomError/ {for(i=0; a[NR-i] !~ /Traceback/; i++) {} i++; while(i-- >= 0) {print a[NR-i]}}' logfile

或者,以文件形式。

{a[NR] = $0};

{
    if ($0 ~ /KevinCustomError/)
    {
        for (i = 0; a[NR-i] !~ /Traceback/; i++)
        {}
        i++
        while (i-- >= 0)
        {
            print a[NR-i];
        }
    }
}

像:awk -f logscript.awk logfile一样使用。

对AWK不太熟悉,所以任何批评都是受欢迎的。基本上,它跟踪到目前为止所读取的所有行,并且只是向后搜索以找到“Traceback”令牌(如果您愿意,可以替换它),然后在中间打印所有行(按照正确的顺序)。

答案 2 :(得分:0)

之前我曾经使用类似的东西来解决类似的问题。作为奖励,如果你多次出现KevinCustomError,它将为每一个提取回溯。

#!/bin/bash

INPUT=$1
TOP='Traceback'
BOTTOM='KevinCustomError'

grep -n "$BOTTOM" $INPUT | while read match
do
    # This gets just the line number from the grep command
    END=${match%%:*}
    # Gets just the part of the file before END, flips it,
    # then gets the line number for TOP
    TEMP=`head -n $END $INPUT | tac | grep -n $TOP`
    # TEMP is really the number of lines from END to Traceback
    START=`expr $END - ${TEMP%%:*} + 1`
    echo $START $END
    sed -n "$START, $END p" < $INPUT
done

在您的测试数据上运行并且回溯了回溯时的输出(因为它更有趣):

4 6
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
KevinCustomError: integer division or modulo by zero

答案 3 :(得分:0)

以下是awk的另一种方式:

awk '
/^KevinCustomError/ { for(;x<length(arry);) print arry[++x]; print $0 } 
/^Traceback/        { delete arry; i=x=0 }
                    { arry[++i]=$0 }
' logFile