【问题标题】:How to grep log files during a specific time period [duplicate]如何在特定时间段内grep日志文件[重复]
【发布时间】:2016-09-14 03:44:13
【问题描述】:

好的,所以我有日志文件,我想在特定范围内搜索。这些范围在一天中会有所不同。下面是一段日志文件,这是我可以给你看的唯一一段,对不起工作。如果这很重要,我正在使用 cat 命令。

工作示例:cat /dir/dir/dir/2014-07-30.txt | grep *someword* | cut -d',' -f1,4,3,7

2014-07-30 19:17:34.542 ;; (p=0,siso=0)

上面为我提供了我需要的信息以及时间戳,但显示了所有时间范围,这就是我想要更正的内容。假设我只希望时间的第一列中的范围为 18 到 20。

实际 --> 2014-07-30 19:17:34.542 ;; (p=0,siso=0)

我正在寻找的唯一范围 --> [18-20]:00:00.000 ;; (p=0,siso=0)

我不担心00s,因为它们可以是任何数字。

感谢收看。从我的示例中您可以看出,我没有使用太多脚本编写方式,但非常感谢任何帮助。

我已经包含了一个日志文件,冒号和逗号是它们应该在的位置。

2014-07-30 14:33:19.259 ;; (p=0,ser=0,siso=0) IN ### Word:Numbers=00000,word=None something goes here and here (something here andhere:here also here:2222),codeword=8,codeword=0,Noideanumbers=00000000,something=something, ;;

【问题讨论】:

  • 这是一个无用的 cat 用于记录。 grep '*someword*' /dir/dir/dir/2014-07-30.txt 做同样的事情,没有额外的进程和管道。
  • 确实可以,但我使用管道和额外的进程,因为我需要日志文件中的某些信息。我意识到并且知道我可以在它面前做 grep。感谢您的意见..
  • 我不关注。那个管道中的猫根本不会为你做任何事情。它不能(除了阻止 grep 知道您正在从文件中读取以及文件名是什么)。
  • 好吧,如果我在前面使用带有管道和分隔符的 grep 的命令,我会得到相同的信息,但在前面的目录信息与我一样,我只得到我需要的信息而没有额外的目录行话。我们一次搜索数百个目录中的日志文件,只需要关键信息。
  • 你说的是 grep 在输入多个文件时放在输出行上的文件名前缀 (/path/to/file:)?因为-h 将其关闭。

标签: linux bash awk grep


【解决方案1】:

使用awk

logsearch() {
    grep "$3" "$4" | awk -v start="$1" -v end="$2" '{split($2, a, /:/)} (a[1] >= start) && (a[1] <= end)'
}

# logsearch <START> <END> <PATTERN> <FILE>
logsearch 18 20 '*someword*' /dir/dir/dir/2014-07-30.txt

或者只有 awk(可能不同的模式引用要求):

logsearch2 ()
{
    awk -v start="$1" -v end="$2" -v pat="$3" '($0 ~ pat) {split($2, a, /:/)} ($0 ~ pat) && (a[1] >= start) && (a[1] <= end)' "$4"
}

【讨论】:

    【解决方案2】:

    没有看到原始输入数据,我从你的剪辑中猜测发生了什么。

    这会给您带来与您想要的结果相似的结果吗?

     awk -F, '/someword/ && $4 ~ /^(18|19|20)/{printf "%s %s %s %s\n", $1,$4,$3,$7}' /dir/dir/dir/2014-07-30.txt
    

    也就是说:一些样本数据通常会有很长的路要走!

    编辑1:

    鉴于您添加到评论和原始帖子中的输入行,以下 awk 语句可以满足您的要求:

    awk '/something/ && $2 ~ /^(18|19|20)/{printf "%s %s %s %s\n", $1,$2,$3,$4} /path/to/your/input_file
    

    【讨论】:

    • 我会看看我能不能创造出一些更好的东西
    • 这是一个示例,冒号和逗号是它们应该在的位置。 2014-07-30 14:33:19.259;; (p=0,ser=0,siso=0) IN ### Word:Numbers=000000000000,word=None 这里和这里的东西(这里和这里的东西:这里还有这里:2222),codeword=8,codeword=0 ,Noideanumbers=00000000,something=something, ;;
    • Hmmm ... 使用该输入,您的剪切会保持线条完好无损。我还是不知道你在做什么。除非你的逗号不是你粘贴的东西。
    • OP 中的剪切修改了该示例行。它并没有从线上下降太多,但确实下降了一点。
    【解决方案3】:

    这是一个非常有趣的问题。纯 BASH 解决方案在您确定响应于感兴趣的日期/时间范围的条目之后,在如何处理或处理条目方面提供了相当多的灵活性。 BASH 中最简单的方法是简单地获取自纪元以来的开始时间和停止时间(以秒为单位),然后测试每个日志条目以确定它是否在该范围内,然后 - 对日志条目执行某些操作。涉及的基本逻辑比较短。日志中 date_time 字段的宽度可以通过将宽度作为参数 4 来设置。根据需要设置默认的dwidth(当前为 15 以匹配 syslog 和 journalctl 格式。唯一需要的参数是日志文件名。如果没有开始/stop 时间指定,它会查找所有条目:

    ## set filename, set start time and stop time (in seconds since epoch) 
    #  and time_field width (number of chars that make up date in log entry)
    lfname=${1}
    test -n "$2" && starttm=`date --date "$2" +%s` || starttm=0
    test -n "$3" && stoptm=`date --date "$3" +%s`  ||  stoptm=${3:-`date --date "Jan 01 2037 00:01:00" +%s`}
    dwidth=${4:-15}
    
    ## read each line from the log file and act on only those with
    #  date_time between starttm and stoptm (inclusive)
    while IFS=$'\n' read line || test -n "$line"; do
    
        test "${line:0:1}" != - || continue           # exclude journalctl first line
        logtm=`date --date "${line:0:$dwidth}" +%s`   # get logtime from entry in seconds since epoch
    
        if test $logtm -ge $starttm && test $logtm -le $stoptm ; then
            echo "logtm: ${line:0:$dwidth} => $logtm"
        fi
    
    done < "${lfname}"
    

    工作示例:

    #!/bin/bash
    
    ## log date format      len
    #   journalctl          15
    #   syslog              15
    #   your log example    23
    
    function usage {
        test -n "$1" && printf "\n Error: %s\n" "$1"
        printf "\n  usage  : %s logfile ['start datetime' 'stop datetime' tmfield_width]\n\n" "${0//*\//}"
        printf "  example: ./date-time-diff.sh syslog \"Jul 31 00:15:02\" \"Jul 31 00:18:30\"\n\n"
        exit 1
    }
    
    ## test for required input & respond to help
    test -n "$1" || usage "insufficient input."
    test "$1" = "-h" || test "$1" = "--help" && usage
    
    ## set filename, set start time and stop time (in seconds since epoch) 
    #  and time_field width (number of chars that make up date in log entry)
    lfname=${1}
    test -n "$2" && starttm=`date --date "$2" +%s` || starttm=0
    test -n "$3" && stoptm=`date --date "$3" +%s`  ||  stoptm=${3:-`date --date "Jan 01 2037 00:01:00" +%s`}
    dwidth=${4:-15}
    
    ## read each line from the log file and act on only those with
    #  date_time between starttm and stoptm (inclusive)
    while IFS=$'\n' read line || test -n "$line"; do
    
        test "${line:0:1}" != - || continue           # exclude journalctl first line
        logtm=`date --date "${line:0:$dwidth}" +%s`   # get logtime from entry in seconds since epoch
    
        if test $logtm -ge $starttm && test $logtm -le $stoptm ; then
            echo "logtm: ${line:0:$dwidth} => $logtm"
        fi
    
    done < "${lfname}"
    
    exit 0
    

    用法:

    $ ./date-time-diff.sh -h
    
      usage  : date-time-diff.sh logfile ['start datetime' 'stop datetime' tmfield_width]
    
      example: ./date-time-diff.sh syslog "Jul 31 00:15:02" "Jul 31 00:18:30"
    

    记得引用你的 starttm 和 stoptm 字符串。在 7 月 31 日 00:12:58 和 7 月 31 日 00:21:10 之间使用日志文件中的 20 个条目进行测试。

    测试输出:

    $ ./date-time-diff.sh jc.log "Jul 31 00:15:02" "Jul 31 00:18:30"
    logtm: Jul 31 00:15:02 => 1406783702
    logtm: Jul 31 00:15:10 => 1406783710
    logtm: Jul 31 00:15:11 => 1406783711
    logtm: Jul 31 00:15:11 => 1406783711
    logtm: Jul 31 00:15:11 => 1406783711
    logtm: Jul 31 00:15:11 => 1406783711
    logtm: Jul 31 00:18:30 => 1406783910
    

    根据您的需要,另一种解决方案可能适合您的需求,但如果您需要能够处理或操作匹配的日志条目,则很难击败 BASH 脚本。

    【讨论】:

      【解决方案4】:

      您可以再次将结果通过管道传输到grep

      cat /dir/dir/dir/2014-07-30.txt | grep someword | cut -d',' -f1,4,3,7 \
          | grep '^\d\d\d\d-\d\d-\d\d \(1[89]\|20\)'
      

      【讨论】:

      • 没有这样的文件或目录错误返回。
      • 这是一个古怪的说法。唯一的文件或目录与您的问题完全相同。
      【解决方案5】:

      我没有足够的声誉来发表评论,但正如 minopret 建议的那样,一次做一个 grep。

      这是获得 18-20 范围的解决方案之一:

      grep ' 20: \| 17:\| 18:' filename.txt
      

      【讨论】:

      • 我不能一次执行一个 grep,因为日志文件包含需要放在同一行的信息。谢谢。
      【解决方案6】:

      我在我正在寻找的表格中找到了答案:

      cat /dir/dir/dir/2014-07-30.txt | grep *someword* | cut -d',' -f1,4,3,7 | egrep '[^ ]+ (2[0-2]):[0-9]'
      

      以下命令从剪辑中获取我需要的所有信息,并用 greps 查找我需要的 someword,使用 egrep 我可以搜索我需要的时间。

      【讨论】:

        猜你喜欢
        • 2013-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-29
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多