Awk 如何获取最后X分钟的日志消息

Awk 如何获取最后X分钟的日志消息,awk,Awk,以下是我的日志格式: 127.0.0.1 user-identifier test [23/Jan/2018:16:45:22 -0700] [WARN ] message 127.0.0.1 user-identifier test [23/Jan/2018:16:55:23 -0700] [WARN ] message 127.0.0.1 user-identifier test [23/Jan/2018:17:00:24 -0700] [WARN ] message 我用这个来获取最后一

以下是我的日志格式:

127.0.0.1 user-identifier test [23/Jan/2018:16:45:22 -0700] [WARN ] message
127.0.0.1 user-identifier test [23/Jan/2018:16:55:23 -0700] [WARN ] message
127.0.0.1 user-identifier test [23/Jan/2018:17:00:24 -0700] [WARN ] message
我用这个来获取最后一个x分钟日志:

awk -v d1="$(date --date="-60 min" "+[%d/%m/%Y:%H:%M:%S")" -v d2="$(date "+[%d/%m/%Y:%H:%M:%S")" '$0 > d1 && $0 < d2' log.log
awk-v d1=“$(日期--date=“-60分钟”+[%d/%m/%Y:%H:%m:%S”)”-v d2=“$(日期”+[%d/%m/%Y:%H:%m:%S”)“$0>d1&$0

但是,它似乎不起作用,因为我的日志不是以日期开始的。我的日志格式应该如何?谢谢

我能找到的最简单的解决方案是解析日志live,添加一个新的日期字段,该字段与简单的算术比较更兼容。例如,让以下内容一直运行:

tail -0F /path/to/logfile | while read line; do
  [[ $line =~ ^([^[]+\[)([^]]+)(.*) ]]
  printf '%s %s%s%s\n' \
    $(date -j -f '%d/%b/%Y:%T %z' "${BASH_REMATCH[2]}" '+%s') \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
done >> /path/to/epochlogfile
请注意,我使用的是BSD
date
,因此我可以使用
-f
控制输入日期格式。您似乎正在使用GNU coreutils的date命令,因此您需要了解如何调整选项以适应。可能类似于:

tail -0F /path/to/logfile | while read line; do
  [[ $line =~ ^([^[]+\[)([^]]+)(.*) ]]
  printf '%s %s%s%s\n' \
    $(d="${BASH_REMATCH[2]}"; d="${d/:/ }"; d="${d//\// }"; date -d "$d" '+%s') \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
done >> /path/to/epochlog
tail -0F /path/to/logfile | gawk '{print systime(),$0}' >> /path/to/epochlog
如果您的
awk
是,您可以选择假定
tail-F
总是在时间戳引用的同时输出日志条目。在这种情况下,您不需要解析日期,您可以使用以下方法简化此过程:

tail -0F /path/to/logfile | while read line; do
  [[ $line =~ ^([^[]+\[)([^]]+)(.*) ]]
  printf '%s %s%s%s\n' \
    $(d="${BASH_REMATCH[2]}"; d="${d/:/ }"; d="${d//\// }"; date -d "$d" '+%s') \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
done >> /path/to/epochlog
tail -0F /path/to/logfile | gawk '{print systime(),$0}' >> /path/to/epochlog
systime()
函数是一个gawk扩展,它以秒为单位返回当前历元。只是重申一下,这些时间将反映当到达日志条目时,
tail
命令,而不是应用程序记录的时间

当然,比让它运行更好的方法是首先使用可搜索的日期创建日志。您还没有说明创建此日志的原因,因此我无法在这方面提出任何具体建议

获得替换日志文件后,可以使用以下内容进行搜索:

#!/usr/bin/env bash

case $(uname -s) in
  Linux)        date_opts=( --date="-60 min" ) ;;
  *BSD|Darwin)  date_opts=( -v-60M ) ;;
  *) echo "No."; exit 1 ;;
esac

start=$(date "${date_opts[@]}" '+%s')

awk -v start="$start" '$1 > start' /path/to/epochlogfile
我跳过了你的
d2
日期条件,因为现在是。这个搜索脚本没有理由需要使用bash,它可以很容易地使用POSIX。我只是很懒。到现在为止,如果对你来说很重要的话,你可能已经足够理解它,可以再次添加它


免责声明:Untested.YMMV.可能包含坚果。

我能看到的最简单的解决方案是解析日志live,添加一个新的日期字段,该字段与简单的算术比较更兼容。例如,让以下内容一直运行:

tail -0F /path/to/logfile | while read line; do
  [[ $line =~ ^([^[]+\[)([^]]+)(.*) ]]
  printf '%s %s%s%s\n' \
    $(date -j -f '%d/%b/%Y:%T %z' "${BASH_REMATCH[2]}" '+%s') \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
done >> /path/to/epochlogfile
请注意,我使用的是BSD
date
,因此我可以使用
-f
控制输入日期格式。您似乎正在使用GNU coreutils的date命令,因此您需要了解如何调整选项以适应。可能类似于:

tail -0F /path/to/logfile | while read line; do
  [[ $line =~ ^([^[]+\[)([^]]+)(.*) ]]
  printf '%s %s%s%s\n' \
    $(d="${BASH_REMATCH[2]}"; d="${d/:/ }"; d="${d//\// }"; date -d "$d" '+%s') \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
done >> /path/to/epochlog
tail -0F /path/to/logfile | gawk '{print systime(),$0}' >> /path/to/epochlog
如果您的
awk
是,您可以选择假定
tail-F
总是在时间戳引用的同时输出日志条目。在这种情况下,您不需要解析日期,您可以使用以下方法简化此过程:

tail -0F /path/to/logfile | while read line; do
  [[ $line =~ ^([^[]+\[)([^]]+)(.*) ]]
  printf '%s %s%s%s\n' \
    $(d="${BASH_REMATCH[2]}"; d="${d/:/ }"; d="${d//\// }"; date -d "$d" '+%s') \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
done >> /path/to/epochlog
tail -0F /path/to/logfile | gawk '{print systime(),$0}' >> /path/to/epochlog
systime()
函数是一个gawk扩展,它以秒为单位返回当前历元。只是重申一下,这些时间将反映当到达日志条目时,
tail
命令,而不是应用程序记录的时间

当然,比让它运行更好的方法是首先使用可搜索的日期创建日志。您还没有说明创建此日志的原因,因此我无法在这方面提出任何具体建议

获得替换日志文件后,可以使用以下内容进行搜索:

#!/usr/bin/env bash

case $(uname -s) in
  Linux)        date_opts=( --date="-60 min" ) ;;
  *BSD|Darwin)  date_opts=( -v-60M ) ;;
  *) echo "No."; exit 1 ;;
esac

start=$(date "${date_opts[@]}" '+%s')

awk -v start="$start" '$1 > start' /path/to/epochlogfile
我跳过了你的
d2
日期条件,因为现在是。这个搜索脚本没有理由需要使用bash,它可以很容易地使用POSIX。我只是很懒。到现在为止,如果对你来说很重要的话,你可能已经足够理解它,可以再次添加它


免责声明:Untested.YMMV.可能包含螺母。

如果您在与生成日志的程序相同的TZ中运行脚本,那么您只需要:

$ cat tst.awk
BEGIN { FS="[[ /:]+" }
{
    mthNr = (index("JanFebMarAprMayJunJulAugSepOctNovDec",$5)+2)/3
    time  = sprintf("%04d%02d%02d%02d%02d%02d", $6, mthNr, $4, $7, $8, $9)
}
time > tgt
它将与任何
awk
一起工作,您将按照以下方式执行:

awk -v tgt="$(date --date='-60 min' +'%Y%m%d%H%M%S')" -f tst.awk

使用您已经使用的支持这些参数的
date
版本。

如果您在与生成日志的版本相同的TZ中运行脚本,那么您只需要:

$ cat tst.awk
BEGIN { FS="[[ /:]+" }
{
    mthNr = (index("JanFebMarAprMayJunJulAugSepOctNovDec",$5)+2)/3
    time  = sprintf("%04d%02d%02d%02d%02d%02d", $6, mthNr, $4, $7, $8, $9)
}
time > tgt
它将与任何
awk
一起工作,您将按照以下方式执行:

awk -v tgt="$(date --date='-60 min' +'%Y%m%d%H%M%S')" -f tst.awk

使用您已经使用的支持这些参数的
date
版本。

awk
在日期管理方面并没有给您太多帮助。如果您将日期存储为纪元秒,那么使用
Hi ghoti比较它们会更容易。谢谢您的建议,我会寻找它。我只是想让简单的sript从这个案例的单文件日志中进行检查。我认为“简单”如果源日期的格式如下,则不可能。
2018年1月23日
的排序始终高于2018年2月1日
。您需要比较历元秒或ISO8601日期。您可能可以重新格式化日期,但这不仅仅是一行代码。您可能更容易编写一些内容来比较时间和否不考虑日期。
awk
在日期管理方面没有给你太多的帮助。如果你将日期存储为纪元秒,那么使用
Hi ghoti比较它们会更容易,谢谢你的建议,我会寻找它。我只想制作一个简单的sript,从这个cas的单文件日志中进行检查e、 我认为“简单”如果源日期的格式如下,则不可能。
2018年1月23日
的排序始终高于2018年2月1日
。您需要比较历元秒或ISO8601日期。您可能可以重新格式化日期,但这不仅仅是一行代码。您可能更容易编写一些内容来比较时间和否不要把日期考虑在内。我想你在阅读时需要
stdbuf-oL tail…
(或者BSD上类似的东西))除此之外,
stdbuf-oL tail | awk
与bash
while read
loop相比不是更好的选择吗?不错的方法,但是FWIW,在GNU awk中,你可以用..@hek2mgl-Heh,actu简化一些事情