【问题标题】:How to speed up this log parser?如何加速这个日志解析器?
【发布时间】:2017-01-06 04:38:23
【问题描述】:

我有一个千兆字节的大日志文件,格式如下:

2016-02-26 08:06:45 Blah blah blah

我有一个日志解析器,它根据日期将单个文件日志拆分为单独的文件,同时从原始行修剪日期。

我确实想要某种形式的tee,这样我就可以看到这个过程有多远了。

问题是这种方法速度慢得让人麻木。有没有办法在 bash 中快速做到这一点?还是我必须编写一个小 C 程序才能做到这一点?

log_file=server.log
log_folder=logs

mkdir $log_folder 2> /dev/null

while read a; do
   date=${a:0:10}

   echo "${a:11}" | tee -a $log_folder/$date
done < <(cat $log_file)

【问题讨论】:

  • 首先你没用过[ cat ]
  • 完成
  • 我想我可能应该扫描文件,直到日期更改,然后将 head | tail 一次将每个块全部写入磁盘。

标签: bash shell logging scripting text-parsing


【解决方案1】:

read 在 bash 中的速度非常慢。你可以让它更快,但你可能可以通过 awk 获得更快的速度:

#!/bin/bash

log_file=input
log_directory=${1-logs}

mkdir -p $log_directory

awk 'NF>1{d=l"/"$1; $1=""; print > d}' l=$log_directory $log_file

如果你真的想打印到标准输出,你可以,但如果这会是一个 tty,它会减慢很多。只需使用:

awk '{d=l"/"$1; $1=""; print > d}1' l=$log_directory $log_file

(注意右大括号后面的“1”。)

【讨论】:

  • 而不是the one,只需跟随$log_directoryls -ltrtail -f,恕我直言。
  • 我错过了什么吗?我收到此错误:awk: cmd. line:1: (FILENAME=server.log FNR=1) fatal: can't redirect to 'logs/' (Is a directory)
  • @JamesBrown :操作人员没有提到他需要关注文件。
  • @Zhro 如果文件中有空行,则会出现该错误。尝试添加 $1 不为空的检查。awk 'NF&gt;1 { d=l"....
  • 如果你有大量的输出文件,你会用完文件句柄。当你看到一个新值时,你可以添加一个 sn-p 来关闭之前的d
【解决方案2】:

试试这个 awk 解决方案 - 它应该很快 - 它显示进度 - 只有一个文件保持打开状态 - 还将不以日期开头的行写入当前日期文件,因此不会丢失行 - 默认初始值如果日志以没有日期的行开头,则日期设置为“0000-00-00”

任何时间比较将不胜感激

dir=$1
if [[ -z $dir ]]; then
  echo >&2 "Usage: $0 outdir <logfile"
  echo >&2 "outdir: directory where output files are created"
  echo >&2 "logfile: input on stdin to split into output files"
  exit 1
fi
mkdir -p $dir
echo "output directory \"$dir\""
awk -vdir=$dir '
BEGIN {
  datepat="[0-9]{4}-[0-9]{2}-[0-9]{2}"
  date="0000-00-00"
  file=dir"/"date
}
date != $1 && $1 ~ datepat {
  if(file) {
    close(file)
    print ""
  }
  print $1 ":"
  date=$1
  file=dir"/"date
}
{
  if($1 ~ datepat)
    line=substr($0,12)
  else
    line=$0
  print line
  print line >file
}
'
head -6 $dir/*

示例输入日志

first line without date
2016-02-26 08:06:45 0 Blah blah blah
2016-02-26 09:06:45 1 Blah blah blah
2016-02-27 07:06:45 2 Blah blah blah
2016-02-27 08:06:45 3 Blah blah blah
no date line
blank lines

another no date line
2016-02-28 07:06:45 4 Blah blah blah
2016-02-28 08:06:45 5 Blah blah blah

输出

first line without date

2016-02-26:
08:06:45 0 Blah blah blah
09:06:45 1 Blah blah blah

2016-02-27:
07:06:45 2 Blah blah blah
08:06:45 3 Blah blah blah
no date line
blank lines

another no date line

2016-02-28:
07:06:45 4 Blah blah blah
08:06:45 5 Blah blah blah

==> tmpd/0000-00-00 <==
first line without date

==> tmpd/2016-02-26 <==
08:06:45 0 Blah blah blah
09:06:45 1 Blah blah blah

==> tmpd/2016-02-27 <==
07:06:45 2 Blah blah blah
08:06:45 3 Blah blah blah
no date line
blank lines

another no date line

==> tmpd/2016-02-28 <==
07:06:45 4 Blah blah blah
08:06:45 5 Blah blah blah

【讨论】:

  • 输入是什么?你会展示如何从命令行运行你的脚本吗?例如,我想将一些文件“server.log”解析到文件夹“logs/”中。
  • 将文件保存到 myscr.sh - 然后./myscr.sh logs &lt;server.log
  • 这太棒了,而且速度非常快。谢谢!
  • 所以一开始效果很好,但是当它到达文件末尾时,它变得很奇怪。一切都很好,直到最后一行 23:12:06.. pastebin 上的错误:pastebin.com/raw/iHLhCwcd
  • 看起来它在没有目录参数的情况下运行 - 我在脚本中添加了一个检查
猜你喜欢
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 2016-12-06
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
  • 2015-08-18
  • 1970-01-01
相关资源
最近更新 更多