GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Mehrere Protokolldateien nach Datum zusammenführen, die auch undatierte Zeilen enthalten (z. B. Stacktraces)

Heikel. Es ist zwar mit date möglich und Bash-Arrays, das ist wirklich die Art von Dingen, die von einer echten Programmiersprache profitieren würden. In Perl zum Beispiel:

$ perl -ne '$d=$1 if /(.+?),/; $k{$d}.=$_; END{print $k{$_} for sort keys(%k);}' log*
01:02:03.6497,2224,0022 foo
foo1
2foo
foo3
01:03:03.6497,2224,0022 FOO
FOO1
2FOO
FOO3
01:04:03.6497,2224,0022 bar
1bar
bar2
3bar

Hier ist dasselbe, unverdichtet in einem kommentierten Skript:

#!/usr/bin/env perl

## Read each input line, saving it 
## as $_. This while loop is equivalent
## to perl -ne 
while (<>) {
    ## If this line has a comma
    if (/(.+?),/) {
        ## Save everything up to the 1st 
        ## comma as $date
        $date=$1;
    }
    ## Add the current line to the %k hash.
    ## The hash's keys are the dates and the 
    ## contents are the lines.
    $k{$date}.=$_;
}

## Get the sorted list of hash keys
@dates=sort(keys(%k));
## Now that we have them sorted, 
## print each set of lines.
foreach $date (@dates) {
    print "$k{$date}";
}

Beachten Sie, dass dies davon ausgeht, dass alle Datumslinien und nur die Datumszeilen enthalten ein Komma. Wenn das nicht der Fall ist, können Sie stattdessen Folgendes verwenden:

perl -ne '$d=$1 if /^(\d+:\d+:\d+\.\d+),/; $k{$d}.=$_; END{print $k{$_} for sort keys(%k);}' log*

Der obige Ansatz muss den gesamten Inhalt der Dateien im Speicher halten. Wenn das ein Problem ist, hier ist eines, das dies nicht tut:

$ perl -pe 's/\n/\0/; s/^/\n/ if /^\d+:\d+:\d+\.\d+/' log* | 
    sort -n | perl -lne 's/\0/\n/g; printf'
01:02:03.6497,2224,0022 foo
foo1
2foo
foo3    
01:03:03.6497,2224,0022 FOO
FOO1
2FOO
FOO3    
01:04:03.6497,2224,0022 bar
1bar
bar2
3bar

Dieser fügt einfach alle Zeilen zwischen aufeinanderfolgenden Zeitstempeln in eine einzige Zeile ein, indem Zeilenumbrüche durch \0 ersetzt werden (Wenn dies in Ihren Protokolldateien enthalten sein kann, verwenden Sie eine beliebige Zeichenfolge, von der Sie wissen, dass sie niemals dort sein wird). Dies wurde an sort weitergegeben und dann tr um die Zeilen zurückzubekommen.

Wie vom OP sehr richtig darauf hingewiesen, müssen alle oben genannten Lösungen umsortiert werden und berücksichtigen nicht, dass die Dateien zusammengeführt werden können. Hier ist eine, die das tut, aber im Gegensatz zu den anderen nur mit zwei Dateien funktioniert:

$ sort -m <(perl -pe 's/\n/\0/; s/^/\n/ if /^\d+:\d+:\d+\.\d+/' log1) \
            <(perl -pe 's/\n/\0/; s/^/\n/ if /^\d+:\d+:\d+\.\d+/' log2) | 
    perl -lne 's/[\0\r]/\n/g; printf'

Und wenn Sie den Perl-Befehl als Alias ​​speichern, erhalten Sie:

$ alias a="perl -pe 's/\n/\0/; s/^/\n/ if /^\d+:\d+:\d+\.\d+/'"
$ sort -m <(a log1) <(a log2) | perl -lne 's/[\0\r]/\n/g; printf'

Linux
  1. So komprimieren Sie mehrere Dateien unter Linux

  2. Alle Dateien erhalten, die an einem bestimmten Datum geändert wurden?

  3. Wie kann man Stderr und Stdout in verschiedene Dateien umleiten und auch im Terminal anzeigen?

  4. Befehl zum Bereinigen alter Protokolldateien?

  5. Dateien finden, für die mehrere Variationen dieses Dateinamens zusammen im selben Verzeichnis vorhanden sind?

So führen Sie unter Linux mehrere PDF-Dateien zu einem PDF zusammen

So verbinden/verschmelzen Sie mehrere Audiodateien zu einer in Linux

Linux-Logdateien

10 großartige Beispiele für das Anzeigen riesiger Protokolldateien in Unix

3 Methoden zum Anzeigen der tail -f-Ausgabe mehrerer Protokolldateien in einem Terminal

Tail mehrere entfernte Dateien