简体   繁体   English

在Linux命令行上按时间戳排序日志文件

[英]sort logfile by timestamp on linux command line

I have a logfile with entries like: 我有一个日志文件,其中包含:

...    
freeswitch.log:2011-09-08 12:21:07.282236 [ERR] ftdm_queue.c:136 Failed to enqueue obj 0x7f2cda3525c0 in queue 0x7f2ce8005990, no more room! windex == rindex == 58!
freeswitch.log:2011-08-08 13:21:07.514261 [ERR] ftdm_queue.c:136 Failed to enqueue obj 0x7f2cda354460 in queue 0x7f2ce8005990, no more room! windex == rindex == 58!
freeswitch.log:2011-06-04 16:21:08.998227 [ERR] ftdm_queue.c:136 Failed to enqueue obj 0x7f2cda356300 in queue 0x7f2ce8005990, no more room! windex == rindex == 58! 
freeswitch.log:2011-09-08 12:21:10.374238 [ERR] ftdm_queue.c:136 Failed to enqueue obj 0x7f2cda3581a0 in queue 0x7f2ce8005990, no more room! windex == rindex == 58!
...

How can I sort the file with linux command line tools by the timestamp in each row decending? 如何使用linux命令行工具按每行的时间戳降序对文件排序?

Use sort 's --stable , --reverse , and --key options: 使用sort--stable ,-- --reverse--key选项:

sort --stable --reverse --key=1,2 freeswitch.log

(For non-didactic purposes, this can be shortened to -srk1,2 .) (出于非教学目的,可以将其缩短为-srk1,2 。)

The sort command (as you might expect) outputs each line of the named files (or STDIN) in sorted order. sort命令(如您期望的那样)按排序顺序输出命名文件(或STDIN)的每一行。 What each of these options does: 这些选项的作用是:

  • The --reverse option tells sort to sort lines with greater values (later dates) higher , rather than lower. --reverse选项告诉sort进行排序线,更大的价值(后日期) 更高 ,而不是更低。 It's assumed, based on other answers, that this is what you mean by "descending" (even though this kind of sorting would normally be considered "ascending"). 根据其他答案,假定这就是您所说的“降序”(即使通常将这种排序视为“升序”)。 If you want to sort the lines in chronological order, you would omit this option. 如果要按时间顺序对行进行排序,则可以忽略此选项。
  • The --key=1,2 option tells sort to only use the first two whitespace-separated "fields" (the "freeswitch.log:"-prefixed date, and the time) as the key for sorting. --key=1,2选项--key=1,2 sort仅使用前两个用空格分隔的“字段”(“ freeswitch.log:”前缀的日期和时间)作为排序关键字。 It is important that you specify the last field to use, even if you are only sorting by one field (for instance, if each line kept time and date together in an ISO-8601 standard field like freeswitch.log 2011-09-08T12:21:07.282236 , you would use -k 2,2 ), as, by default, the fields used by a key extend to the end of the line . 即使您仅按一个字段进行排序,也要指定要使用的最后一个字段,这一点很重要(例如,如果每一行都将时间和日期保存在ISO-8601标准字段中,例如freeswitch.log 2011-09-08T12:21:07.282236 ,则应使用-k 2,2 ),因为默认情况下,键所使用的字段扩展到该行的末尾
  • The --stable option tells sort to not perform "last-resort ordering". --stable选项--stable sort不执行“最后排序”。 Without this option, a line with two equal keys (as specified with the --keys option) will then be sorted according to the entire line , meaning that the filename and/or content will change the sort order of the lines. 如果没有此选项,则将根据整个行对具有两个相等键的行(由--keys选项指定)进行排序,这意味着文件名和/或内容将更改行的排序顺序。

It is important to specify both extents of the --key , as well as the --stable option. 重要的是指定--key范围以及--stable选项。 Without them, multiple lines of output that occurred at the same time (in other words, a multi-line message) would be sorted according to the content of the message (without the second field in --key ) and/or the filename (without --stable , if the filename is a separate field, as described below). 如果没有它们,将根据消息的内容(在--key没有第二个字段)和/或文件名(在同一时间出现的多行输出(换句话说,多行消息)进行排序)。如果文件名是一个单独的字段,则不带--stable ,如下所述。

In other words, a log message like this: 换句话说,这样的日志消息:

freeswitch.log:2011-09-08 12:21:10.374238 Warning: Syntax error on line 20:
freeswitch.log:2011-09-08 12:21:10.374238
freeswitch.log:2011-09-08 12:21:10.374238    My[brackets(call)
freeswitch.log:2011-09-08 12:21:10.374238               ^
freeswitch.log:2011-09-08 12:21:10.374238 Suggestion:
freeswitch.log:2011-09-08 12:21:10.374238   did you forget to
freeswitch.log:2011-09-08 12:21:10.374238   close your brackets?

would get "sorted" into: 将被“分类”为:

freeswitch.log:2011-09-08 12:21:10.374238
freeswitch.log:2011-09-08 12:21:10.374238               ^
freeswitch.log:2011-09-08 12:21:10.374238   close your brackets?
freeswitch.log:2011-09-08 12:21:10.374238   did you forget to
freeswitch.log:2011-09-08 12:21:10.374238    My[brackets(call)
freeswitch.log:2011-09-08 12:21:10.374238 Suggestion:
freeswitch.log:2011-09-08 12:21:10.374238 Warning: Syntax error on line 20:

This is "sorted" (because "c" comes before "d", and "S" comes before "W"), but it's not in order . 这是“排序的” (因为“ c”在“ d”之前,而“ S”在“ W”之前),但顺序不正确 Specifying --stable (and keeping your --key bounded) will skip the extra sorting and preserve the order , which is what you want. 指定--stable (并保持--key限制)将跳过多余的排序并保留order ,这就是您想要的。


Also, sorting by this combined filename-and-date field will only work if every line in your output starts with the same filename. 另外,仅当输出中的每一行都以相同的文件名开头时,才可以使用此文件名和日期组合字段进行排序。 Given the syntax you posted, if your input has multiple, different filenames that you want to ignore in sorting, you need to use a program like sed to convert the filename to its own space-separated field, then pipe the converted lines to sort (after which you may then convert the field separators back): 根据您发布的语法,如果您的输入包含多个不同的文件名,您希望在排序时忽略它们,则需要使用sed类的程序将文件名转换为以空格分隔的字段,然后使用管道将转换后的行进行sort (之后,您可以将字段分隔符转换回去):

sed 's/:/ /' freeswitch.log | sort -srk2,3 | sed 's/ /:/'

Note that the fields used by the key are changed to 2,3 , skipping the first (filename) field. 请注意,该键使用的字段更改为2,3 ,跳过了第一个(文件名)字段。

Use sort 's -k flag: 使用sort的-k标志:

sort -k1 -r freeswitch.log

That will sort the file, in reverse, by the first key (ie freeswitch.log:2011-09-08 12:21:07.282236). 这将通过第一个键对文件进行反向排序(即freeswitch.log:2011-09-08 12:21:07.282236)。 If the filename is always the same (freeswitch.log), then it should sort by the date. 如果文件名始终相同(freeswitch.log),则应按日期排序。

您可以使用

sort -r

Crude but effective technique: Prefix each line with a numeric representation of the date, sort numerically, then remove the extra info. 粗略但有效的技术:在每一行前面加上日期的数字表示,按数字排序,然后删除多余的信息。

Oneliner: Oneliner:

while IFS=' ' read -r name_date trailing ; do date=$(cut -d: -f2 <<<"$name_date") ; printf '%s:%s\n' $(date -d "$date" +%s) "$name_date $trailing" ; done < freeswitch.log | sort -k1 -t: | cut -d: -f2-

Shell script: Shell脚本:

#!/usr/bin/env bash

logfile="$1"

if [ -f "$logfile" ] ; then
    while IFS=' ' read -r name_date trailing ; do
            date=$(cut -d: -f2 <<<"$name_date")
        printf '%s:%s\n' $(date -d "$date" +%s) "$name_date $trailing"
    done < "$logfile" | sort -k1 -t: | cut -d: -f2-
fi

Note: Requires GNU date. 注意:需要GNU日期。

If the output at this point is the reverse of what you want it is simple to pipe through tac or to modify the script to also pass -r to sort . 如果此时的输出与您想要的相反,则很容易通过tac进行管道传输或将脚本修改为也传递-r进行sort

EDIT: I missed the part where the filename was literally on each line. 编辑:我错过了文件名实际上在每一行上的部分。 Updated version will now actually work. 现在可以实际使用更新的版本。

您可以尝试使用排序

sort -k1,2 file

The log file seems ascending, you can 日志文件似乎在上升,您可以

tac yourlogfile

which would reversely show your log file. 这将反向显示您的日志文件。

I guess the log file appends new data at the end. 我猜该日志文件将在末尾附加新数据。 If so, you may read the file in reverse. 如果是这样,您可以反向读取文件。 Try with tail -r or cat command. 尝试使用tail -rcat命令。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM