【问题标题】:awk command to get all records from log file based on timestamp range in pythonawk命令根据python中的时间戳范围从日志文件中获取所有记录
【发布时间】:2016-08-24 21:26:44
【问题描述】:

我需要获取两个时间戳 1 到时间戳 2 之间的所有记录。 这是两个时间戳的示例:2016-03-21T11:20:27、2016-03-21T11:40:27

这是我尝试过的:

import subprocess

query = '$0 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/ \
{ \
    if ($1T$2 >= "2016-03-21T11:20:27") p=1; \
    if ($1T$2 >= "2016-03-21T11:40:27") p=2; \
} \
p {print $0}' 


output = subprocess.Popen(['awk', query,'nat.csv.2016032112.csv.gz'],stdout=subprocess.PIPE).communicate()[0]

我不确定我错过了什么。


编辑:zgrep 命令的输入和输出

命令: zgrep "192.168.224.63,39713" nat.csv.2016032112.csv.gz

输出:(返回2条记录)

2016-03-21T11:01:13.054-04:00,2,172.21.63.13,49766,17.167.195.12,443,192.168.224.63,39713,6,16,1438,13,6506 2016-03-21T11:31:16.528-04:00,54,172.21.63.24,59014,77.68.41.125,51900,192.168.224.63,39713,6,182,236501,125,6437

有了这个,我可以解析字段以返回 IP 地址和端口号以供其他用途。由于我想要一个范围之间的数据,时间戳 A 和时间戳 B 之间的数据,我想过滤该范围之外的任何内容。


编辑 2 提供的参数

ip address: 192.168.224.154

port: 36715

log: nat.csv.2016032100.csv.gz

start: 2016-03-20T23:12:00

end: 2016-03-20T23:22:00

输入

2016-03-20T23:00:01.671-04:00,60,172.21.154.211,40500,24.43.1.206,18313,192.168.224.154,36715,17,2,454,1,129
2016-03-20T23:12:22.714-04:00,16,172.21.154.161,61130,31.13.73.7,80,192.168.224.154,36715,6,4,172,2,92

结果提供者:

zgrep "192.168.224.154,36715" nat.csv.2016032100.csv.gz

输出

2016-03-20T23:12:22.714-04:00,16,172.21.154.161,61130,31.13.73.7,80,192.168.224.154,36715,6,4,172,2,92

第一条记录不应该返回。很难找到好的例子,大多数返回 2 条记录。


这是一个多么棒的日志

2016-03-20T23:00:01.671-04:00   19  172.21.128.70   61807   154.70.22.157   15702   192.168.224.128 61065   6   3   152 0   0
2016-03-20T23:00:01.671-04:00   19  172.19.172.152  57681   189.110.82.196  1024    192.168.226.172 41197   6   3   152 0   0
2016-03-20T23:00:01.671-04:00   19  172.19.165.121  24598   222.89.181.20   9094    192.168.226.165 32628   6   5   300 0   0
2016-03-20T23:00:01.671-04:00   19  172.25.47.36    58797   192.168.0.6 49201   192.168.244.2   36050   6   7   448 0   0
2016-03-20T23:00:01.671-04:00   19  172.19.165.121  24254   114.228.60.157  58782   192.168.226.165 51470   6   1   60  0   0
2016-03-20T23:00:01.671-04:00   4   172.19.168.238  57419   8.8.4.4 53  192.168.226.168 51143   17  1   60  1   76
2016-03-20T23:00:01.671-04:00   4   172.21.134.249  58220   8.8.4.4 53  192.168.224.134 50374   17  1   68  1   267
2016-03-20T23:00:01.671-04:00   3   172.19.131.110  52480   156.154.70.22   53  192.168.226.131 53024   17  1   68  1   166
2016-03-20T23:00:01.671-04:00   3   172.19.131.110  64935   156.154.70.22   53  192.168.226.131 53193   17  1   67  1   155
2016-03-20T23:00:01.671-04:00   68  172.19.212.211  52537   31.13.73.1  443 192.168.226.212 62342   6   24  4426    20  5142
2016-03-20T23:00:01.671-04:00   77  172.19.170.63   51375   104.73.87.51    443 192.168.226.170 54179   6   9   860 7   553
2016-03-20T23:00:01.671-04:00   43  172.19.170.63   60547   23.15.135.11    80  192.168.226.170 42232   6   5   212 4   585
2016-03-20T23:00:01.671-04:00   44  172.19.170.63   60530   23.15.135.18    80  192.168.226.170 47914   6   5   212 4   585
2016-03-20T23:00:01.671-04:00   73  172.19.153.239  54157   199.16.156.6    443 192.168.226.153 42815   6   16  4429    12  6298
2016-03-20T23:00:01.671-04:00   76  172.19.170.63   51393   104.73.87.51    443 192.168.226.170 58126   6   9   1407    7   862
2016-03-20T23:00:01.671-04:00   6   172.21.155.59   57297   54.225.73.60    80  192.168.224.155 45142   6   7   980 6   897
2016-03-20T23:00:01.671-04:00   7   172.21.155.59   57283   8.43.72.32  80  192.168.224.155 55636   6   9   4855    7   868
2016-03-20T23:00:01.671-04:00   7   172.21.155.59   57275   23.235.39.175   80  192.168.224.155 58325   6   33  3674    44  59257
2016-03-20T23:00:01.671-04:00   6   172.21.155.59   57304   23.21.59.91 80  192.168.224.155 49043   6   7   2921    6   2384

我使用 zgrep 命令来解析我需要的记录。另外,为了限制结果。

【问题讨论】:

  • 您的代码实际执行的操作与您希望执行的操作有何不同?
  • 我曾经有一个查询,它需要一个时间戳并返回日志中的确切记录。我当时用了grep。 query = ["zgrep", "'", ip_address, ",", port_number, "'", log_file] query = "".join(query) records.append([subprocess.Popen(query, shell = True, stdout = subprocess.PIPE).stdout.read()]) 但是,现在我们想看看日志中两个日志时间戳之间发生了什么。我不相信 grep 是处理范围的最佳方式。我看到网上有人使用 sed 或 awk 命令。我以前从未使用过其中任何一个。现在什么都没有显示。
  • 第二个 if 语句应设置 p=0 以使其按预期工作。如果您的日志已被订购,则最好在此时退出。

标签: python linux logging awk


【解决方案1】:

您遇到的一个明确问题是$1T$2 将 $1 与名为 T 的未初始化(以及值为 0 或 NULL 的数字字符串)变量的内容连接起来,然后连接 $2 ,所以它与刚刚做的相同$1$2。你的意思可能是$1"T"$2

query = '/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/ \
{ \
    if ($1"T"$2 >= "2016-03-21T11:20:27") p=1; \
    if ($1"T"$2 >= "2016-03-21T11:40:27") p=2; \
} \
p'

我也做了一些调整,让它变得更加古怪。

不太可能成为问题的是某些 awks 可能不理解 {2}(例如,没有 --re-interval 的 4.0 之前的 GNU awks)。

话虽如此:请原谅我的无知,但为什么必须调用 awk 来执行此操作? python不是有一些读取文件和比较文本的方法吗?

此外,如果 nat.csv.2016032112.csv.gz 是您尝试用作 awk 输入的文件的名称,那么如果该文件真的被 gzip 压缩(从 .gz 后缀猜测),您将遇到问题,因为 awk 仅在文本上运行文件。

鉴于您的更新问题,我认为这可能是您想要的 awk 脚本:

$ cat tst.awk
BEGIN {
    beg = "2016-03-20T23:12:00"
    end = "2016-03-20T23:22:00"
}
match($0,/^[0-9]{4}(-[0-9]{2}){2}T[0-2][0-9](:[0-5][0-9]){2}/) {
    cur = substr($0,RSTART,RLENGTH)
}
cur >= beg { inBlock = 1 }
inBlock
cur >= end { inBlock = 0 }

$ awk -f tst.awk file
2016-03-20T23:12:22.714-04:00,16,172.21.154.161,61130,31.13.73.7,80,192.168.224.154,36715,6,4,172,2,92

当您说“介于”时,不清楚您的意思是包含或排除与开始和/或结束值匹配的行。无论您需要什么,只需重新排序或调整上面最后 3 行中的数学运算即可完成。

鉴于我现在对您的输入格式的了解,您真正需要的是:

awk '$0>="2016-03-20T23:12:00"{p=1} p; $0>="2016-03-20T23:22:00"{p=0}'

【讨论】:

  • 每个日志大约 4Gb,我打算做类似的事情:zgrep ipaddress.portnumber logfile | awk 时间范围过滤器。 awk 将过滤 zgrep 返回的结果。至少这是计划。
  • 如果您知道开始时间、结束时间和要搜索的文件,您会不会碰巧知道解析数据的更好方法?一旦返回记录,就可以解析记录字段。拉回的数据将用于查询数据库。 Python 有像 subprocess 这样的模块,允许在 python 中进行终端交互。
  • 我编辑了上面的帖子以显示 .csv.gz 文件中的示例。我只是研究如何让终端正确显示。然后我知道如何将它移植到 python。
  • 感谢 Ed,这行得通。我正在使用它来测试我的 python 应用程序。我选择了 karakfa 在我的 python 程序中给出的答案。我将继续努力沟通,我在工作中被告知我无法解释自己,谢谢您的反馈:)
  • 不客气,这很好,但您应该知道@karakfa 的脚本对于您的输入文件毫无意义。例如,给定一个像 2016-03-20T23:12:22.714-04:00,16,172.21.154.161,... 这样的输入行,$1 包含 2016-03-20T23:12:22.714-04:00 而 $2 包含 16,因此脚本正在创建一个 2016-03-20T23:12:22.714-04:00T16 的键,用于与像 2016-03-20T23:12:00 这样的时间戳进行比较。当然,它会产生您期望的输出,但这样做没有任何意义。我在答案中添加了一个脚本,可以用最少的代码完成您需要的工作。
【解决方案2】:

你可以重写awk脚本如下

awk -F, -v OFS=, '{key=$1"T"$2}
         key >= "2016-03-21T11:20:27" {p=1}
         key >= "2016-03-21T11:40:27" {exit}
         p'

您也可以将时间戳正则表达式匹配委托给 zgrep。

【讨论】:

  • 嗨 karakfa,我在 python 应用程序中使用了你的代码,它可以工作。非常感谢:)
【解决方案3】:

感谢 Ed Morton 和 karakfa 的反馈。

这是终端中运行的命令:

终端中的命令

zgrep "192.168.224.63,39713" nat.csv.2016032112.csv.gz | awk -F, -v OFS=, '{key=$1"T"$2} key >= "2016-03-21T11:20:27" {p=1} key >= "2016-03-21T11:40:27" {exit} p'

结果(未过滤,没有 awk)

2016-03-21T11:01:13.054-04:00,2,172.21.63.13,49766,17.167.195.12,443,192.168.224.63,39713,6,16,1438,13,6506
2016-03-21T11:31:16.528-04:00,54,172.21.63.24,59014,77.68.41.125,51900,192.168.224.63,39713,6,182,236501,125,6437

结果(过滤,使用 awk)

2016-03-21T11:31:16.528-04:00,54,172.21.63.24,59014,77.68.41.125,51900,192.168.224.63,39713,6,182,236501,125,6437   

所以,这里是python代码:

import subprocess

ip_address = '192.168.224.63'
port_number = '39713'
log_file = 'nat.csv.2016032112.csv.gz'
start_time = '2016-03-21T11:20:27'
stop_time = '2016-03-21T11:40:27'

terminal_commands = {}
terminal_commands['zgrep'] = ["zgrep", " '", ip_address, ",", port_number, "' ", log_file]
terminal_commands['awk'] = ["awk -F, -v OFS=, '{key=$1\"T\"$2} key >= \"",start_time,"\" {p=1} key >= \"",stop_time,"\" {exit} p'"]

query_commands = {}
query_commands['zgrep'] = ''.join(str(x) for x in terminal_commands['zgrep'])
query_commands['awk'] = ''.join(str(x) for x in terminal_commands['awk'])
query_commands['run_query'] = '|'.join((query_commands['zgrep'], query_commands['awk']))

records = []
records.append([subprocess.Popen(query_commands['run_query'], shell = True, stdout = subprocess.PIPE).stdout.read()])
print records

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 2021-01-29
    • 2013-09-10
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    相关资源
    最近更新 更多