按日期合并多个日志文件,包括多行

时间:2013-04-07 19:25:27

标签: sorting logging command-line cat log-files

我有几个日志包含所有以时间戳开头的行,以便以下工作按预期合并它们:

cat myLog1.txt myLog2.txt | sort -n > combined.txt

问题是,myLog2.txt还可以包含没有时间戳的行(例如java堆栈跟踪)。是否有一种简单的方法,没有任何自定义脚本仍然合并它们并保留多行内容?

示例 myLog1.txt

11:48:18.825 [main] INFO  org.hibernate.cfg.Environment - HHH000206: hibernate.properties not found
11:48:55.784 [main] INFO  o.h.tool.hbm2ddl.SchemaUpdate - HHH000396: Updating schema

示例 myLog2.txt

11:48:35.377 [qtp1484319352-19] ERROR c.w.b.c.ControllerErrorHandler -
org.springframework.beans.TypeMismatchException: Failed to convert value of type   'java.lang.String' to required type 'org.joda.time.LocalDate'; nested exception is    org.springframework.core.convert.ConversionFailedException: Failed to convert from type     java.lang.String to type @org.springframework.web.bind.annotation.RequestParam   @org.springframework.format.annotation.DateTimeFormat org.joda.time.LocalDate for value    '[2013-03-26]'; nested exception is java.lang.IllegalArgumentException: Invalid format: "    [2013-03-26]"
    at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:68) ~[spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45) ~[spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:595) ~[spring-context-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:98) ~[spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) ~[spring-web-3.2.1.RELEAS

预期输出

11:48:18.825 [main] INFO  org.hibernate.cfg.Environment - HHH000206: hibernate.properties not found
11:48:35.377 [qtp1484319352-19] ERROR c.w.b.c.ControllerErrorHandler -
org.springframework.beans.TypeMismatchException: Failed to convert value of type   'java.lang.String' to required type 'org.joda.time.LocalDate'; nested exception is    org.springframework.core.convert.ConversionFailedException: Failed to convert from type     java.lang.String to type @org.springframework.web.bind.annotation.RequestParam   @org.springframework.format.annotation.DateTimeFormat org.joda.time.LocalDate for value    '[2013-03-26]'; nested exception is java.lang.IllegalArgumentException: Invalid format: "    [2013-03-26]"
    at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:68) ~[spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45) ~[spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:595) ~[spring-context-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:98) ~[spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) ~[spring-web-3.2.1.RELEAS
11:48:55.784 [main] INFO  o.h.tool.hbm2ddl.SchemaUpdate - HHH000396: Updating schema

由于 马可

5 个答案:

答案 0 :(得分:17)

我正在努力解决同样的问题,最后我想我已经得到了它。尝试这样做:

sort -nbms -k1.1,1.2 -k1.4,1.5 -k1.7,1.8 -k1.10,1.12 myLog1.txt myLog2.txt > combined.txt

我自己还不完全清楚,但我会尝试给出一些解释。根据使用的手册页面意思是:

  

-n, - numeric-sort - 根据字符串数值进行比较。

     

-b, - ignore-leading-blanks - 忽略前导空白。

     

-s, - stable - 通过禁用最后的比较来稳定排序

     

-m,--merge - 合并已排序的文件;不要排序

     

-k, - key = POS1 [,POS2] - 在POS1(原点1)开始一个键,在POS2(默认行尾)结束

  • 日志文件已经订购,因此我们不需要再次对它们进行排序,只确定合并时哪条线路在哪里。这就是-m的原因。保持堆栈跟踪不被破坏是至关重要的。
  • 在这种情况下,
  • -b不是必需的,因为以某种方式-n-m组合使得堆栈跟踪线不会聚集。我留下它以防万一,因为大多数堆栈跟踪线都以空白开头。
  • 只要密钥中存在非数字字符,
  • -n显然会停止比较密钥。这是保持堆栈跟踪到位的第二个关键点。重要的是,如果它是-n -k1,1,它只会按小时对日志文件进行排序,因为冒号是非数字的。除了-n加速数字比较,所以无论如何我们想要它。
  • 通过指向每个键中的特定字符位置来解决前一点中提到的问题,这就是为什么-k1.1,1.2(小时的第一和第二位)-k1.4,1.5(第一和第二)分钟数)等等。点之前的第一个数字始终是&#39; 1&#39;因为它指向文件行的第一列(在我们的例子中是时间)。简而言之,-kA,B AB是给定行中的列位置(默认情况下,行由空格分隔)。使用的A和B的格式是..请记住,只要AB之间存在非数字字符,如果使用了-n,则在比较之后将忽略它。< / LI>
  • -s禁用默认行为,即:每当进行比较的键都完成相同的完整字符串比较。我们不希望保留原始日志条目顺序。不确定-m是否有必要。

答案 1 :(得分:1)

Nope - 无法使用简单的命令IMMHO完成。

但是 - 这是一个脚本(这是一个挑战......)

@ECHO OFF
SETLOCAL
:: First log to tempfile
COPY /y mylog.txt "%temp%\combinedlogs.tmp" >NUL
(
FOR /f "delims=" %%i IN (mylog2.txt) DO (
 SET line=%%i
 ECHO %%i|FINDSTR /b /r "[012][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9][0-9][0-9]" >NUL
 IF ERRORLEVEL 1 (
  SETLOCAL ENABLEDELAYEDEXPANSION
 ECHO(!stamp:~0,12!!count!!line!
  ENDLOCAL
  SET /a count+=1
 ) ELSE (
 SET /a count=100
 ECHO %%i
 SET stamp=%%i
 )
)
)>>"%temp%\combinedlogs.tmp"
(
FOR /f "delims=" %%i IN ('SORT "%temp%\combinedlogs.tmp"') DO (
 SET line=%%i
 SETLOCAL enabledelayedexpansion
 IF "!line:~12,1!"==" " (ECHO(%%i) ELSE (ECHO(!line:~15!)
 ENDLOCAL
)
)>combinedlogs.txt
DEL "%temp%\combinedlogs.tmp" /F /Q

将带有所有带时间戳的条目的第一个日志复制到临时文件
通过

处理第二个文件
  • 直接输出任何带时间戳的行,保存戳记行并设置3位数的计数器
  • 为其他行输出标记部分+计数器+原始文本 撞到柜台

Tempfile因此是

Timestamp1 line1 from file1
..
Timestampn linen from file1
timestampA line1 from file2 with timestamp
timestampA100 UNtimestamped line2from file2
timestampA101 UNtimestamped line3from file2
timestampB line4 from file2 with timestamp
timestampB100 UNtimestamped line5from file2
timestampB101 UNtimestamped line6from file2
...

对结果进行排序并重新处理
第13个字符中包含非空格的行是来自第二个文件的未加时间戳的行,因此

  • 输出除前15个字符之外的所有字符(时间戳12个字符+ 3个用于 计数器)
  • 否则,带有时间戳的行,所以输出全部。

完成!

答案 2 :(得分:0)

您应该在日志文件中使用mergestableignore-leading-blanksnumeric-sort以及易于排序的日期时间格式(例如yyyyMMddHHmmssSSS

因此,我更改了您的日志格式,以便更容易排序,从而产生sort -bsnm log1 log2

 $ cat -n log1 log2 && sort -m -b -n -s log1 log2
      1 114818825 [main] INFO  org.hibernate.cfg.Environment - HHH000206 hibernate.properties not found
      2 114855784 [main] INFO  o.h.tool.hbm2ddl.SchemaUpdate - HHH000396 Updating schema
      1 114835377 [qtp1484319352-19] ERROR c.w.b.c.ControllerErrorHandler -
      2 org.springframework.beans.TypeMismatchException Failed to convert value of type   'java.lang.String' to required type 'org.joda.time.LocalDate'; nested exception is    org.springframework.core.convert.ConversionFailedException Failed to convert from type     java.lang.String to type @org.springframework.web.bind.annotation.RequestParam   @org.springframework.format.annotation.DateTimeFormat org.joda.time.LocalDate for value    '[2013-03-26]'; nested exception is java.lang.IllegalArgumentException Invalid format "    [2013-03-26]"
      3     at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java68) ~[spring-beans-3.2.1.RELEASE.jar3.2.1.RELEASE]
      4 at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java45) ~[spring-beans-3.2.1.RELEASE.jar3.2.1.RELEASE]
      5 at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java595) ~[spring-context-3.2.1.RELEASE.jar3.2.1.RELEASE]
      6 at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java98) ~[spring-web-3.2.1.RELEASE.jar3.2.1.RELEASE]
      7 at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java77) ~[spring-web-3.2.1.RELEASE.jar3.2.1.RELEASE]
      8 at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java162) ~[spring-web-3.2.1.RELEAS
      9 
 114818825 [main] INFO  org.hibernate.cfg.Environment - HHH000206 hibernate.properties not found
 114835377 [qtp1484319352-19] ERROR c.w.b.c.ControllerErrorHandler -
 org.springframework.beans.TypeMismatchException Failed to convert value of type   'java.lang.String' to required type 'org.joda.time.LocalDate'; nested exception is    org.springframework.core.convert.ConversionFailedException Failed to convert from type     java.lang.String to type @org.springframework.web.bind.annotation.RequestParam   @org.springframework.format.annotation.DateTimeFormat org.joda.time.LocalDate for value    '[2013-03-26]'; nested exception is java.lang.IllegalArgumentException Invalid format "    [2013-03-26]"
     at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java68) ~[spring-beans-3.2.1.RELEASE.jar3.2.1.RELEASE]
 at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java45) ~[spring-beans-3.2.1.RELEASE.jar3.2.1.RELEASE]
 at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java595) ~[spring-context-3.2.1.RELEASE.jar3.2.1.RELEASE]
 at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java98) ~[spring-web-3.2.1.RELEASE.jar3.2.1.RELEASE]
 at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java77) ~[spring-web-3.2.1.RELEASE.jar3.2.1.RELEASE]
 at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java162) ~[spring-web-3.2.1.RELEAS

 114855784 [main] INFO  o.h.tool.hbm2ddl.SchemaUpdate - HHH000396 Updating schema

@Magoo's answer所述,您的日志日期时间目前格式化的方式很难排序。

答案 3 :(得分:0)

这是在bash shell中使用简单合并文件(而不是昂贵的求助 - 在日志文件已经排序的情况下)的一种方法。这对于数百兆字节或更多的大型文件非常重要,实际日志文件就是如此。

此解决方案假设您的日志中没有NUL字节,对于我遇到的每个日志文件都是如此,具有各种字符集。

基本理念:

  1. 通过在每个输入文件中用NUL替换这些换行符,将所有多行转换为单行
  2. 对已替换的文件执行sorn -m以合并它们
  3. 将NUL替换为合并结果的换行符
  4. 第一步是多次完成,我给它起了一个别名:

    alias a="awk '{ if (match(\$0, /^[0-9]{2}:[0-9]{2}:[0-9]{2}\\./, _))\
    { if (NR == 1) printf \"%s\", \$0; else printf \"\\n%s\", \$0 }\
    else printf \"\\0%s\", \$0 } END { print \"\" }'"
    

    这是执行所有3个步骤的命令:

    sort -m <(a myLog1.txt) <(a myLog2.txt) | tr '\0' '\n'
    

    有关详情,请参阅https://superuser.com/a/838446/125379

答案 4 :(得分:0)

开放源代码工具(Java GitHub)使您可以将包括多行在内的不同格式的日志文件合并到合并文件中。

该工具允许更改日志文件中记录的时间。当文件来自不同时区时很有用。

它还允许为合并的文件生成其他信息,例如统一格式的应用程序名称或时间戳,请参见the example

该工具可用作command line toolJava library。 注意:我是作者。