我需要帮助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的提示吗?
答案 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');
$
注意:
NetworkDevice=
模式对我来说似乎不够。我用NetworkDeviceName=
替换了它。 (如果我错了,应该很容易替换它。)
我不知道如何为postgres
正确格式化输出,也不知道提问者的数据库结构。因此,可能必须调整print
语句。 (脚本中只有一个print
语句。)但是,print
语句输出到标准输出通道(您可能已经预期的那样)。因此,它可以轻松地用于任何其他输入消费过程。
目前尚不清楚是否要求所有模式必须匹配或(至少)一个
我实施了“至少一个”
要实现“全部”,||
语句中的if
运算符必须由&&
运算符替换。 (脚本中只有一个if
语句。)
不幸的是,gensub()
函数仅在GNU awk中可用。对于非GNU awk,可以使用gsub()
来完成另一个解决方案。但是,gensub()
函数使用起来更方便。因此,只要没有明确要求非GNU awk解决方案,我更喜欢它。