2016-03-22 6 views
4

Ich habe zwei Protokolldateien, denen ein sortierbarer Zeitsatz vorangestellt ist. Ich möchte sie in der Reihenfolge sehen, während die Prozesse, die die Protokolldateien generieren, noch ausgeführt werden. Dies ist eine ziemlich getreue Simulation der Situation:sortierte Dateien mit minimaler Pufferung zusammenführen

slow() { 
    # print stdout at 30bps 
    exec pv -qL 30 
} 
timestamp() { 
    # prefix stdin with a sortable timestamp 
    exec tai64n 
} 

# Simulate two slowly-running batch jobs: 
seq 000 099 | slow | timestamp > seq.1 & 
seq1=$! 
seq 100 199 | slow | timestamp > seq.2 & 
seq2=$! 

# I'd like to see the combined output of those two logs, in timestamp-sorted order 
try1() { 
    # this shows me the output as soon as it's available, 
    # but it's badly interleaved and not necessarily in order 
    tail -f seq.1 --pid=$seq1 & 
    tail -f seq.2 --pid=$seq2 & 
} 
try2() { 
    # this gives the correct output, 
    # but outputs nothing till both jobs have stopped 
    sort -sm <(tail -f seq.1 --pid=$seq1) <(tail -f seq.2 --pid=$seq2) 
} 


try2 
wait 
+0

Ah, du hast schon bemerkt "nichts, bis beide Jobs aufgehört haben", was für mich richtig klingt. Wenn Sie Daten wie "y, x, w, a, b, c, z" haben, müssen Sie alles lesen, um die richtige Reihenfolge zu erhalten. Für sehr nahe Daten, wie Ihre Zeitstempel sind, könnten Sie ein Pufferungssystem erstellen, aber yikes! Tolles Q übrigens! Viel Glück! – shellter

+2

Es sollte sicherlich möglich sein, in "Chunks" zu puffern, so dass Sie nahezu sortierte Log-Ausgaben in Echtzeit erhalten (Ausgabe-Logs pro Minute oder so), aber Sie müssen ein Fenster dafür auswählen, und Ihre Logs würden ablegen in großen Mengen. –

+0

Die beiden Streams sind bereits sortiert, so dass ein System nur den Puffer pro Zeile benötigt. An diesem Punkt kann es den kleineren der beiden drucken und trotzdem eine gut sortierte Ausgabe garantieren. Ich kann das sicherlich in Python schreiben, aber ich hatte auf ein bereits erfundenes Dienstprogramm gehofft. Ich denke eigentlich, 'sort -m' sollte so funktionieren ... – bukzor

Antwort

0

Die solution using tee (die Dateien zu schreiben, so dass die Standard-Ausgabe an die Konsole geht noch) nicht, da tee unerwünschte Latenzzeit führt und löst nicht die Problem. Ebenso konnte ich keine Lösungen mit tail -f -s 0.01 (die die Abfrage auf 100/s ändert) und/oder eine Art von Anruf wie split --filter='sort -sm' zum Sortieren kleiner Chargen erhalten.

ich nicht tai64n auch haben, so dass mein Testcode dieses funktional identisch Perl Code verwendet:

tai64n() { 
    perl -MTime::HiRes=time -pe ' 
    printf "\@4%015x%x%n", split(/\./,time), $c; print 0 x(25-$c) . " "' 
} 

Nachdem es nicht gelungen, diese zu lösen mit sh und bash übte ich meine Standard-Failover, perl:

slow() { 
    # print stdout at 30bps 
    pv -qL 30 
} 

tai64n_and_tee() { 
    # prefix stdin with a sortable timestamp and copy to given file 
    perl -MTime::HiRes=time -e ' 
    $_ = shift; 
    open(TEE, "> $_") or die $!; 
    while (<>) { 
     $_ = sprintf("\@4%015x%x%n", split(/\./,time), $c) . 0 x(25-$c) . " $_"; 
     print TEE $_; 
     print $_; 
    } 
    ' "$1" 
} 

# Simulate two slowly-running batch jobs: 
seq 000 099 | slow | tai64n_and_tee seq.1 & 
seq 100 199 | slow | tai64n_and_tee seq.2 & 
wait 

Das war praktisch für mich, weil ich bereits perl für den Zeitstempel verwendet hatte. Ich habe dies nicht mit perl als tai64n und eine separate perl Anruf handeln als tee handeln, aber es könnte mit der realen tai64n arbeiten.

+0

Wenn ich Ihre Perl für 'tai64n' subtrahiere, bekomme ich keine Ausgabe, bis die Prozesse enden, und die Ausgabe wird nicht sortiert. – bukzor

+0

Wenn ich stattdessen 'tai64n' mit Ihrem obigen Bash-Skript verwende, ist die Ausgabe schlecht verschachtelt; Einige Zeilen haben zwei Zeitstempel, andere keine. – bukzor

+0

Okay, ich hatte in meinen Tests vor der Veröffentlichung nicht wirklich 'Tee' aufgerufen. Ich sehe dein Problem und habe die Antwort umgeschrieben. In derselben Schleife fügt dieser Perl-Code die Zeitstempel _und_ Kopien zu jeder gegebenen Protokolldatei hinzu. Ich bezweifle, dass eine Perl-Approximation von 'tee' mit dem echten' tai64n' funktionieren wird (wahrscheinlich der gleiche Grund, warum das echte 'tee' hier nicht funktioniert, nicht dass ich das verstehe ...) –