我有一个巨大的日志文件 access.log ,其中包含以下条目:
192.11.111.111 - - [05/Mar/2021:00:00:02 +0100] "GET ..."
192.250.14.80 - - [05/Mar/2021:00:00:09 +0100] "GET ..."
12.249.66.42 - - [05/Mar/2021:00:00:13 +0100] "GET ..."
如何仅获取/过滤最后一小时的条目?
答案1
#!/bin/bash
age() { python -c '
import sys
from datetime import datetime
print(int((datetime.now() - datetime.strptime(sys.argv[1], sys.argv[2])).seconds))
' "$@"
}
tac access.log | while IFS= read line; do
date=$(cut -d' ' -f4 <<< "$line")
age=$(age "$date" "[%d/%b/%Y:%H:%M:%S")
[ $age -gt 3600 ] && break
printf '%s\n' "$line"
done
解释:
- 创建一个函数来获取日期字符串的年龄,我使用
python
datetime
模块。 - 然后反向循环文件的行
tac log | while ...
- 使用 获取日期字符串
cut
。-d' '
如果分隔符是制表符而不是空格,则需要删除- 或
awk '{print $4}' <<< "$line"
改用 - 或使用
read ip some thing date tz else <<< "$line"
)。
- 使用我们在第一步中定义的函数获取年龄
- 当秒> 3600(=1小时)时,停止循环(
break
) - 否则,打印该行(或执行任何操作)
一些附加说明:
由于我忽略时区(+0100),这假设我们与日志文件位于同一时区。如果您有其他时区的日志文件,您可能需要改进该
age
功能。看这里并将日期读取为cut -d' ' -f4,5
.显然,您可以使用 来完成整个操作
python
,但是,反向读取文件而不必读取整个文件似乎没那么容易我只是喜欢tac
。您可以使用
date
andbc
或 so 来计算年龄 (就像这里完成的一样),但是由于您的日期格式不受开箱即用的支持,这将是一个痛苦。伊莫,datetime.strptime
非常适合。该函数的优点是
age
:它对于任何类型的任务都非常可重用。只要称呼它相同strptime
就可以读取它并且是记录在这里。age "date_string" "format"