2013-04-07 1 views
6

j'ai plusieurs journaux contenant toutes les lignes commençant par un horodatage, de sorte que les travaux suivants devraient les fusionner:La fusion de plusieurs fichiers journaux par date, y compris multilignes

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

Le problème est que myLog2.txt peut aussi contenir des lignes sans horodatage (par exemple, des traces de pile java). Existe-t-il un moyen facile sans scripts personnalisés de les fusionner et de conserver le contenu multiligne?

Exemple 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 

Exemple 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 

de sortie prévue

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 

Merci Marco

+0

Merci pour l'exemple @marco. A m'a aidé à comprendre le même problème pour moi-même. – yegeniy

Répondre

1

Nope - ne peut pas être fait avec une simple commande IMMHO.

Mais - voici un script pour le faire (c'était un défi ...)

@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 

Copiez le premier journal avec toutes-horodatés entrées à un tempfile
Process le second fichier par

  • délivrer en sortie une ligne horodaté directement, l'enregistrement de la ligne de timbre et la fixation d'un compteur à 3 chiffres
  • en sortie la partie de tampon + compteur + Originaltext pour d'autres lignes et heurtant le compteur

fichier temporaire est donc

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 
... 

Tri le résultat et le retraitement
Une ligne avec un non-espace dans le 13e caractère est une ligne untimestamped à partir du second fichier, de sorte

    sortie
  • tout sauf les 15 premiers caractères (horodatage 12 caractères + 3 pour compteur)
  • sinon, ligne horodatée, donc tout sortie.

Fait!

0

Vous devez utiliser le merge, stable, ignore-leading-blanks, numeric-sort, et un format datetime facilement triables (comme yyyyMMddHHmmssSSS) dans vos fichiers journaux.

Alors, je l'ai changé le format de journal pour être plus facilement classable, ce qui 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 

Comme le dit @Magoo's answer, la façon dont le datetime de vos journaux est actuellement formaté est difficile à trier.

+0

Cela va visser des entrées de journal multi-lignes en «triant» les stacktraces, n'est-ce pas? – topr

+0

Salut @topr, ça faisait un moment, mais d'après ce que je me rappelle avoir vu, les stacktraces multi-lignes sont conservés avec 'sort -bsnm log1 log2 ...'. Je ne serais pas surpris s'il y avait des cas de coin, mais pour l'exemple @marco fourni et mon propre usage cela a fonctionné étonnamment bien. Il existe une variété d'outils de visualisation de journal là-bas si vous avez besoin de quelque chose de plus sophistiqué. – yegeniy

+0

Merci pour votre réponse. Les empilements sont préservés mais avec ces commutateurs toutes les lignes sont préservées quand même. Il n'y a pas de tri du tout, juste de fusion. J'utilise l'outil de visualisation de journal, mais mon besoin de fusionner avec tri est que j'ai plusieurs fichiers journaux et il est beaucoup plus pratique de nourrir l'outil avec un seul fichier. – topr

0

Voici une façon de le faire dans un shell bash avec fusion simple des fichiers (plutôt que coûteux - comme les fichiers journaux sont déjà triés). Ceci est important pour les fichiers volumineux de plusieurs centaines de mégaoctets ou plus, comme c'est souvent le cas avec les fichiers journaux du monde réel.

Cette solution suppose qu'il n'y a aucun octets NUL dans vos journaux, ce qui est vrai pour chaque fichier journal que j'ai rencontré, avec différents jeux de caractères.

L'idée de base:

  1. Concat tous multilignes à une seule ligne en remplaçant les sauts de ligne par NUL dans chaque fichier d'entrée
  2. Faites un sorn -m sur les fichiers remplacés pour les fusionner
  3. retour Remplacer NUL à sur les nouvelles lignes du résultat fusionné

Comme la première étape est fait plusieurs fois, je lui ai donné un alias:

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 \"\" }'" 

est ici la commande qui exécute les 3 étapes:

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

Pour plus, voir https://superuser.com/a/838446/125379

5

je luttais avec le même problème et finalement je pense que je l'ai. Essayez le faire comme:

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

Il est pas encore tout à fait clair pour moi, je vais essayer de donner quelques explications bien. D'après les pages de manuel utilisées, les commutateurs signifient:

-n, --numérique -type - compare en fonction de la valeur numérique de la chaîne.

-b, --ignore-leading-blanks - Ignore les blancs de début.

-s, --stable - stabilisent le tri en inhibant la comparaison de dernier recours

-m, --merge - fusionner des fichiers déjà triés; ne pas trier

-k, --key = POS1 [, POS2] - lancer une clé à POS1 (origine 1), mettre fin à POS2 (fin par défaut de la ligne)

  • fichiers journaux sont déjà commandés, donc nous n'avons pas besoin de les trier à nouveau, seulement déterminer quelle ligne va où lors de la fusion. C'est pourquoi -m. Il est crucial d'éviter que les stacktraces ne soient brouillés.
  • -b n'est pas nécessaire dans ce cas car -n et -m combiné empêche les lignes stacktrace de se regrouper. Je l'ai laissé juste au cas où la plupart des lignes stacktrace commence par des espaces.
  • -n semble cesser de comparer la clé chaque fois qu'il y a un caractère non numérique dans la clé. C'est le deuxième élément crucial pour garder les stacktraces en place. Il est important de savoir que si c'était -n -k1,1, les fichiers journaux ne seraient triés que par heure car les deux-points ne sont pas numériques. En dehors de cela -n accélère la comparaison numérique de sorte que nous aimerions l'avoir de toute façon.
  • le problème mentionné dans le point précédent est résolu en pointant sur des positions de caractères spécifiques dans chaque touche, c'est pourquoi -k1.1,1.2 (premier et deuxième chiffre de l'heure) -k1.4,1.5 (premier et deuxième chiffre de minutes) et ainsi de suite. Le premier chiffre avant le point est toujours '1' car il pointe vers la première colonne de la ligne de fichier (ce qui dans notre cas est le temps). En bref, -kA,BA et B sont des positions de colonnes dans une ligne donnée (par défaut, les lignes sont délimitées par des espaces). Format de A et B utilisé est .. Gardez à l'esprit que chaque fois qu'il y a un caractère non numérique entre A et B tout ce qui après il sera ignoré en comparaison si -n utilisé.
  • -s désactive le comportement par défaut qui est: à chaque fois que les clés par lesquelles la comparaison est effectuée, la même comparaison de chaînes complètes est effectuée. Nous ne voulons pas que cela conserve l'ordre des entrées de journal d'origine. Je ne sais pas si c'est nécessaire avec -m cependant.
+0

Bravo @topr! Si votre format de journal n'est pas un simple tri numérique, vous devez vous battre avec le drapeau -k. J'ai trouvé plus simple de modifier l'horodatage en un format datetime facilement triable (comme aaaaMMddHHmmssSSS), mais il est plus difficile à lire. – yegeniy

Questions connexes