如何从实时日志中提取数据并将其传递给postgres

时间:2017-05-15 05:04:07

标签: linux bash postgresql awk sed

我需要帮助awk / grep / sed或者你认为可以做任何事情。 我有一个日志文件,需要持续监控它,并在写入新行时从新行中获取一些数据。

新行很长且没有结构化,但它们将包含以下模式UserName=SOMEUSRNAME, NetworkDevice=SOMENETWORKDEVICE, Calling-Station-ID=SOMEMACADDRESS

〔实施例:
May 15 03:59:16 MTN-LAB-ISE-B1 CISE_Passed_Authentications 0000043297 1 0 2017-05-15 03:59:16.979 +00:00 0013123384 5200 NOTICE Passed-Authentication: Authentication succeeded, ConfigVersionId=170, Device IP Address=10.97.31.130, DestinationIPAddress=10.62.56.152, DestinationPort=1812, UserName=abcd\testuser, Protocol=Radius, RequestLatency=313, NetworkDeviceName=SHROCLUSW-WLAN-LAB, User-Name=d4d748fefe96, NAS-IP-Address=10.97.31.130, NAS-Port=50005, Service-Type=Call Check, Framed-IP-Address=10.97.109.64, Framed-MTU=1500, Called-Station-ID=64-E9-50-B6-DE-05, Calling-Station-ID=D4-D7-48-FE-FE-96, NAS-Port-Type=Ethernet, NAS-Port-Id=GigabitEthernet0/5, EAP-Key-Name=,

我在考虑使用tail -f来监视日志文件并将其传递给grep / sed / awk以提取所需的数据。 我只需要SOMEUSERNAME,SOMENETWORKDEVICE,SOMEMACADDRESS而不是模式。

当然,在完成提取后,这需要将其管理到postgres。

有人可以给我一些关于如何进行匹配/提取部分以及管道到postgres的提示吗?

1 个答案:

答案 0 :(得分:0)

这也可以用grep / sed完成,但我个人更喜欢awk。

我做了这个简短的脚本filter.awk

{
  # find info in line
  userName = gensub(/^.*UserName=([^,\r\n]+).*$/, "\\1", 1, $0)
  networkDevice = gensub(/^.*NetworkDeviceName=([^,\r\n]+).*$/, "\\1", 1, $0)
  callingStationId = gensub(/^.*Calling-Station-ID=([^,\r\n]+).*$/, "\\1", 1, $0)
  # print filtered info (if any of patterns matched)
  if (userName != "" || networkDevice != "" || callingStationId != "") {
    print "INSERT INTO logs (username, networkdevice, calling_station_id) VALUES ('"userName"', '"networkDevice"', '"callingStationId"');"
  }
  # If "all patterns" is required instead of "any pattern"
  # the "||" operators have to be replaced with "&&".
}

我在cygwin的bash上用GNU awk测试了它(Window 10):

$ cat >filter.txt <<EOF
> May 15 03:59:16 MTN-LAB-ISE-B1 CISE_Passed_Authentications 0000043297 1 0 2017-05-15 03:59:16.979 +00:00 0013123384 5200 NOTICE Passed-Authentication: Authentication succeeded, ConfigVersionId=170, Device IP Address=10.97.31.130, DestinationIPAddress=10.62.56.152, DestinationPort=1812, UserName=abcd\testuser, Protocol=Radius, RequestLatency=313, NetworkDeviceName=SHROCLUSW-WLAN-LAB, User-Name=d4d748fefe96, NAS-IP-Address=10.97.31.130, NAS-Port=50005, Service-Type=Call Check, Framed-IP-Address=10.97.109.64, Framed-MTU=1500, Called-Station-ID=64-E9-50-B6-DE-05, Calling-Station-ID=D4-D7-48-FE-FE-96, NAS-Port-Type=Ethernet, NAS-Port-Id=GigabitEthernet0/5, EAP-Key-Name=,
> EOF

$ awk -f filter.awk filter.txt
INSERT INTO logs (username, networkdevice, calling_station_id) VALUES ('abcd\testuser', 'SHROCLUSW-WLAN-LAB', 'D4-D7-48-FE-FE-96');

$

注意:

  1. NetworkDevice=模式对我来说似乎不够。我用NetworkDeviceName=替换了它。 (如果我错了,应该很容易替换它。)

  2. 我不知道如何为postgres正确格式化输出,也不知道提问者的数据库结构。因此,可能必须调整print语句。 (脚本中只有一个print语句。)但是,print语句输出到标准输出通道(您可能已经预期的那样)。因此,它可以轻松地用于任何其他输入消费过程。

  3. 目前尚不清楚是否要求所有模式必须匹配或(至少)一个 我实施了“至少一个” 要实现“全部”,||语句中的if运算符必须由&&运算符替换。 (脚本中只有一个if语句。)

  4. 不幸的是,gensub()函数仅在GNU awk中可用。对于非GNU awk,可以使用gsub()来完成另一个解决方案。但是,gensub()函数使用起来更方便。因此,只要没有明确要求非GNU awk解决方案,我更喜欢它。