Linux读取日志文件并进行筛选,以仅获取一次相同类型的日志消息

Linux读取日志文件并进行筛选,以仅获取一次相同类型的日志消息,linux,shell,ubuntu,grep,uniq,Linux,Shell,Ubuntu,Grep,Uniq,在我的日志文件中,我有三种类型的日志消息:信息、警告和错误。我只想抓取错误消息,但由于存在不同类型的错误消息,并且同一错误消息可能会在日志文件中出现多次,因此我只想抓取每种类型的错误消息 只有一次。我可以在Ubuntu终端中使用什么命令?我试过: grep -E 'level=error' server.log | sort --unique 但这也给了我“信息”和“警告”信息 然后我使用了这个命令,但仍然得到了所有三种类型的消息,而不仅仅是错误消息 grep 'error' server.l

在我的日志文件中,我有三种类型的日志消息:信息、警告和错误。我只想抓取错误消息,但由于存在不同类型的错误消息,并且同一错误消息可能会在日志文件中出现多次,因此我只想抓取每种类型的错误消息 只有一次。我可以在Ubuntu终端中使用什么命令?我试过:

grep -E 'level=error' server.log | sort --unique
但这也给了我“信息”和“警告”信息

然后我使用了这个命令,但仍然得到了所有三种类型的消息,而不仅仅是错误消息

grep 'error' server.log | uniq -f 1
参数-f1用于跳过timestamp字段,因为它总是唯一的

例如,我的日志消息是:

.
.
.
11-03-2020 11:53:32" level=info msg="Starting up" file="etc/load/startwith.txt"
11-03-2020 11:53:33" level=info msg="Started" file="etc/load/startwith.txt"
11-03-2020 11:54:29" level=warning msg="Some fields missing" file="etc/load/startwith.php" 
11-03-2020 11:54:47" level=info msg="Started the process" file="etc/load/startwith.php" 
11-03-2020 11:54:51" level=info msg="Connecting to database" file="etc/db/dbinfo.php" 
11-03-2020 11:54:53" level=error msg="Database connection failed" file="etc/db/dbinfo.php"  
11-03-2020 13:26:22" level=info msg="Started back-up process" file="etc/load/startwith.php" 
11-03-2020 13:26:23" level=info msg="Starting up" file="etc/load/startwith.txt"
11-03-2020 13:26:26" level=error msg="Start up failed" file="etc/db/startwith.php" 
11-03-2020 13:26:27" level=info msg="Starting up" file="etc/load/startwith.txt"
11-03-2020 13:26:31" level=error msg="Start up failed" file="etc/db/startwith.php"
11-03-2020 13:26:32" level=info msg="Starting up" file="etc/load/startwith.txt"
11-03-2020 13:26:35" level=warning msg="Duplicate fields found" file="etc/load/startwith.php" 
11-03-2020 13:26:36" level=info msg="Started the process" file="etc/load/startwith.php" 
11-03-2020 13:26:37" level=info msg="Connecting to database" file="etc/db/dbinfo.php"
11-03-2020 13:26:38" level=info msg="Success. Connected to the database" file="etc/db/db-success.php"
11-03-2020 13:26:38" level=info msg="Inserting data to database" file="etc/db/dboperation.php"
11-03-2020 13:26:39" level=warning msg="Null fields found" file="etc/db/dboperation.php"
11-03-2020 13:26:39" level=info msg="Data inserted" file="etc/db/dboperation.php"
11-03-2020 13:26:39" level=info msg="Disconnected" file="etc/db/dboperation.php"
11-03-2020 13:26:43" level=info msg="Inserting data to database" file="etc/db/dboperation.php"
11-03-2020 13:26:43" level=error msg="Required data missing" file="etc/db/dboperation.php"
11-03-2020 13:26:44" level=info msg="Inserting data to database" file="etc/db/dboperation.php"
11-03-2020 13:26:44" level=error msg="Required data missing" file="etc/db/dboperation.php"
.
.
.
上述日志中错误的预期输出(3种不同类型的错误,而不是总的错误发生次数)为:

11-03-2020 11:54:53" level=error msg="Database connection failed" file="etc/db/dbinfo.php" 
11-03-2020 13:26:31" level=error msg="Start up failed" file="etc/db/startwith.php"
11-03-2020 13:26:44" level=error msg="Required data missing" file="etc/db/dboperation.php"

因此,本质上我需要过滤日志文件以获取错误消息,并且每种类型只有一个错误。

命令
uniq-f1
按空格分割。它没有效果,因为第一个空格(时间)后面的字符串是唯一的

改用uniq-s 20。这将忽略前20个字符


它适用于时间戳,因为在大多数情况下时间戳的长度是固定的。

命令
uniq-f 1
按空格分割。它没有效果,因为第一个空格(时间)后面的字符串是唯一的

改用uniq-s 20。这将忽略前20个字符

它适用于时间戳,因为在大多数情况下时间戳的长度是固定的。

只是:

awk '/error/ && !seen[$4]++'
或者使用引号作为分隔符来包含完整的
msg=“this text”
消息,如:

awk -F'"' '/error/ && !seen[$3]++'
您可以在没有awk-
grep错误的情况下进行排序,然后
nl
对行进行编号,然后
sort-u
使用
msg=
对字段进行唯一排序,然后对行号重新排序,并使用
cut
删除行号。或者,可以使用
sed
提取
msg=“part”
,以简化
sort
标记化。像这样:

grep error | sed 's/.* msg="\([^"]*\)"/\1\t&/' | nl -w1 |
sort -t $'\t' -u -k2,2 | sort -n -k1 | cut -f3-
只是:

或者使用引号作为分隔符来包含完整的
msg=“this text”
消息,如:

awk -F'"' '/error/ && !seen[$3]++'
您可以在没有awk-
grep错误的情况下进行排序,然后
nl
对行进行编号,然后
sort-u
使用
msg=
对字段进行唯一排序,然后对行号重新排序,并使用
cut
删除行号。或者,可以使用
sed
提取
msg=“part”
,以简化
sort
标记化。像这样:

grep error | sed 's/.* msg="\([^"]*\)"/\1\t&/' | nl -w1 |
sort -t $'\t' -u -k2,2 | sort -n -k1 | cut -f3-

这回答了你的问题吗?抱歉,它没有回答我的问题,因为他正在比较(因此排除)包含时间戳的行的精确副本,而我只想在时间戳之后进行比较。所以<代码>awk'!看到[$4]+'
。。。他使用
作为字段分隔符,并使用第一个字段。因此,使用另一个字段分隔符和另一个字段……这是否回答了您的问题?抱歉,它没有回答我的问题,因为他正在比较(因此排除)包含时间戳的行的精确副本,而我只想在时间戳之后进行比较。所以<代码>awk'!看到[$4]+'
。。。他使用
作为字段分隔符,并使用第一个字段。因此,请使用另一个字段分隔符和另一个字段……您能描述一下
!看到[$4]+
了吗?谢谢Kamil,如果我想在一个大日志文件中过滤所有三种类型的消息(信息、警告、错误),我该如何修改这个
'/error/&&!看到[$4]+'
命令吗?
awk'/error/'
类似于
grep error
。只需删除
”/error/&&
部分。您能描述一下
是什么吗!看到[$4]+
了吗?谢谢Kamil,如果我想在一个大日志文件中过滤所有三种类型的消息(信息、警告、错误),我该如何修改这个
'/error/&&!看到[$4]+'
命令吗?
awk'/error/'
类似于
grep error
。只需删除
'/error/&&
部分