【问题标题】:How can I use awk or grep to capture an entire Python traceback in a log file?如何使用 awk 或 grep 在日志文件中捕获整个 Python 回溯?
【发布时间】:2013-07-07 17:17:20
【问题描述】:

一个日志文件包含许多 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

【问题讨论】:

  • 我会推荐awk。它在处理此类事情时效果更好,因为您可以在处理数据时跨多行存储状态(使用变量)。
  • 我认为实际的回溯不只是 3 行长,对吧?例如,它们是可变长度的。
  • voithos,没错
  • 这些标准输出是输出异常还是您使用 python 日志记录?
  • 我们正在调用 logging.exception

标签: python logging awk grep


【解决方案1】:

这是我尝试拼凑的一个 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”标记(如果您愿意,可以替换它),然后打印中间的所有内容(以正确的顺序)。

【讨论】:

  • 我没有检查过,也不确定我是否理解了日志的一般结构,但我怀疑for 可以从i = 1 开始,除非KevinCustomError 可以在与前面的Traceback 相同的行。
【解决方案2】:

如果我已经正确理解了 Python 日志文件的结构,下面是一个很小的sed 解决方案,它不像看起来那么神秘

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

总而言之,脚本仅对以Traceback 开头的行执行操作;在这些行上,脚本不断添加一个新行 (N) 并随后检查新添加的行是否以 KevinCustomError 开头;如果是这种情况,则脚本分支到末尾并打印多行模式空间;如果不是,脚本会从模式空间中删除除最后一行 Traceback-starting 之外的所有内容,然后分支回到 :here 并附加另一行 (N),依此类推。

具体来说,它的工作原理如下:

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

【讨论】:

    【解决方案3】:

    这是awk的另一种方式:

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

    【讨论】:

      【解决方案4】:

      我以前用过类似的东西来解决类似的问题。作为奖励,如果您多次出现 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
      

      【讨论】:

        猜你喜欢
        • 2017-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-20
        • 2017-03-24
        • 1970-01-01
        • 2020-05-20
        • 2015-09-17
        相关资源
        最近更新 更多