bash – 使用awk,grep,sed解析大型日志文件(~5gb)的性能问题

前端之家收集整理的这篇文章主要介绍了bash – 使用awk,grep,sed解析大型日志文件(~5gb)的性能问题前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我目前正在处理大小约为的日志文件. 5GB.我是解析日志文件和使用UNIX bash的新手,所以我会尽量精确.在搜索日志文件时,我执行以下操作:提供要查找的请求编号,然后可选地将操作作为辅助过滤器提供.典型的命令如下所示:
fgrep '2064351200' example.log | fgrep 'action: example'

这可以很好地处理较小的文件,但是使用5gb的日志文件,它的速度无法忍受.我在网上看到使用sed或awk来提高性能(或者甚至可能是两者的组合)都很棒,但我不确定这是如何实现的.例如,使用awk,我有一个典型的命令:

awk '/2064351200/ {print}' example.log

基本上我的最终目标是能够打印/返回包含字符串的记录(或行号)(可能高达4-5,并且我读过管道很糟糕)以便在日志文件中有效匹配.

在旁注中,在bash shell中,如果我想使用awk并进行一些处理,那是如何实现的呢?例如:

BEGIN { print "File\tOwner" }
{ print $8,"\t",\
$3}
END { print " - DONE -" }

这是一个非常简单的awk脚本,我认为有一种方法可以将它放入一个单行bash命令中?但我不确定结构是怎样的.

在此先感谢您的帮助.干杯.

您需要执行一些测试以找出瓶颈的位置,以及各种工具的执行速度.尝试这样的测试:
time fgrep '2064351200' example.log >/dev/null
time egrep '2064351200' example.log >/dev/null
time sed -e '/2064351200/!d' example.log >/dev/null
time awk '/2064351200/ {print}' example.log >/dev/null

传统上,egrep应该是最快的(是的,比fgrep更快),但是一些现代实现是自适应的并且自动切换到最合适的搜索算法.如果您有bmgrep(使用Boyer-Moore搜索算法),请尝试使用.通常,sed和awk会更慢,因为它们被设计为更通用的文本操作工具,而不是针对特定的搜索工作进行调整.但它确实取决于实现,找到的正确方法是运行测试.每次运行它们几次,这样你就不会被缓存和竞争过程搞砸了.

正如@Ron指出的那样,您的搜索过程可能是磁盘I / O绑定.如果您将多次搜索同一个日志文件,则首先压缩日志文件可能会更快;这样可以更快地读取磁盘,但需要更多的cpu时间来处理,因为它必须首先解压缩.尝试这样的事情:

compress -c example2.log >example2.log.Z
time zgrep '2064351200' example2.log.Z >/dev/null
gzip -c example2.log >example2.log.gz
time zgrep '2064351200' example2.log.gz >/dev/null
bzip2 -k example.log
time bzgrep '2064351200' example.log.bz2 >/dev/null

我只是用一个相当可压缩的文本文件运行了一个快速测试,发现bzip2压缩得最好,但后来耗费了更多的cpu时间进行解压缩,所以zgip选项总体来说最快.您的计算机将具有与我的不同的磁盘和cpu性能,因此您的结果可能会有所不同.如果您有任何其他压缩机,也可以尝试它们,和/或尝试不同级别的gzip压缩等.

说到预处理:如果你一遍又一遍地搜索同一个日志,有没有办法预先选择你可能感兴趣的日志行?如果是这样,将它们变成一个较小的(可能是压缩的)文件,然后搜索它而不是整个文件.与压缩一样,您可以预先花费一些额外的时间,但每次单独搜索都会更快.

关于管道的注意事项:其他条件相同,通过多个命令管理一个巨大的文件将比单个命令完成所有工作要慢.但是这里的所有事情都不相同,如果在管道中使用多个命令(这是zgrep和bzgrep所做的)会为你带来更好的整体性能,那就去吧.另外,请考虑您是否实际将所有数据传递到整个管道.在你给出的例子中,fgrep’2064351200’example.log | fgrep’action:example’,第一个fgrep将丢弃大部分文件;管道和第二个命令只需处理包含’2064351200’的小部分日志,因此减速可能可以忽略不计.

tl;博士测试所有的事情!

编辑:如果日志文件是“实时”(即添加新条目),但它的大部分是静态的,您可能可以使用部分预处理方法:压缩(&可能预扫描)日志,然后当扫描使用压缩(& /预扫描)版本加上自执行预扫描后添加的日志部分的尾部.像这样的东西:

# Precompress:
gzip -v -c example.log >example.log.gz
compressedsize=$(gzip -l example.log.gz | awk '{if(NR==2) print $2}')

# Search the compressed file + recent additions:
{ gzip -cdfq example.log.gz; tail -c +$compressedsize example.log; } | egrep '2064351200'

如果您要进行多个相关搜索(例如特定请求,然后是该请求的特定操作),您可以保存预扫描版本:

# Prescan for a particular request (repeat for each request you'll be working with):
gzip -cdfq example.log.gz | egrep '2064351200' > prescan-2064351200.log

# Search the prescanned file + recent additions:
{ cat prescan-2064351200.log; tail -c +$compressedsize example.log | egrep '2064351200'; } | egrep 'action: example'

猜你在找的Bash相关文章