Wie zgrep die Letzte Zeile einer gz-Datei, ohne Schwanz
Hier ist mein problem, ich habe eine Reihe von big gz
log-Dateien, die erste info in der Zeile ist ein datetime-text, z.B.: 2014-03-20 05:32:00.
Muss ich schauen, was der log-Dateien hat einen spezifischen Daten.
Für die init habe ich einfach ein:
'-query-data-'
zgrep -m 1 '^20140320-04' 20140320-0{3,4}*gz
ABER WIE tun Sie das gleiche mit der letzten Zeile, ohne Prozess, ohne die ganze Datei als getan hätten, mit zcat (zu schwer):
zcat foo.gz | tail -1
Zusätzliche Informationen, die diese Protokolle erstellt werden, mit den Daten, Zeitpunkt der erstmaligen Aufzeichnung, also, wenn ich Abfragen will meldet um 14:00:00 ich Suche, auch in Dateien, die erstellt werden, BEVOR 14:00:00, als die Datei erstellt würde, um 13:50:00 Uhr und geschlossen um 14:10:00 Uhr.
- Wegen der Art, wie die Kompression funktioniert, ist es nicht möglich, zu Lesen das Ende der Datei, ohne zu entpacken alles, bevor es.
- gibt es ein Muster auf grep mach Ende der Datei, wie es bei den end-of-line
$
- Nein, gibt es nicht.
zgrep
ist im Grunde nur Rohrleitungenzcat
zugrep
, so was ist falsch mitzcat foo.gz | tail -1 | grep
? - Mit großen Binärdateien sind Sie faul.
- Aber da es die gleiche Arbeit, wie
zgrep
Sie gar nichts speichern, indem nichtzcat
. - auch mit der
-m
option? Vielleicht check this out nur mit der "mit der Quelle", ein Blick in zgrep ' s code. Funktioniert es mit Trauben?/Zeile für Zeile?/ganze Datei? Wenn dem so ist, zgrep ist kaum ein "alias" zuzcat | grep
... - Es könnte in der Tat mit
zlib
intern, aber das hat zu tun im wesentlichen die gleiche Arbeit.-m
Stoppt das Lesen von der Eingabe, wenn es das limit erreicht, aber es hat immer noch zu Lesen, vom Anfang der Datei bis es dort ankommt. Ich sehe nicht, wie das ist keine Hilfe, wenn Sie versuchen zu finden die Letzte Zeile. - Das hilft, um das erste vorkommen von Datum / Uhrzeit in eine Datei, damit ich weiß, es passt, aber für Dateien, die erstellt wurde, bevor meine abgefragt datetime und fischte nach, es ist schneller, um rückwärts zu suchen.
- Das problem ist, dass die komprimierten Daten sind schwer zu Prozess nach hinten. Stream-Kompression-algorithmen wie LZW, basieren auf adaptiven algorithmen, und der Leser zum verarbeiten der komprimierten Daten, um zu lernen, die Kompressionen, wie es geht.
- Erhöht man die Frequenz auf
logrotate
(oder was auch immer komprimiert die log-Dateien), so dass Sie kleinere, komprimierte Dateien zu suchen? Das wird den Aufwand zu verringern, Dekomprimieren Sie die Datei, die ist einem gegeben. - Nur in der nächsten version... und das würde lange, lange...
- Ist es eine option zum komprimieren der Datei mit bgzip und index der bgzipped-Datei mit tabix?
- vielleicht, aber nur für weitere Versionen. Wenn Sie wollen, um es als eine Antwort werde ich akzeptieren.
- Danke, aber ich glaube nicht, dass es eine ausreichend gute Antwort. In der Zwischenzeit möchte ich Sie direkt auf diese Seite stackoverflow.com/questions/429987/... stackoverflow.com/questions/236414/... lh3.github.io/2014/07/05/random-access-to-zlib-komprimierte-Dateien
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die einfachste Lösung wäre, ändern Sie Ihre log-rotation, erstellen von kleineren Dateien.
Die zweite einfachste Lösung wäre die Verwendung einer Kompressions-tool unterstützt den wahlfreien Zugriff.
Projekte wie dictzip, BGZF, und csio jedes add sync-flush Punkte in unterschiedlichen Abständen innerhalb von gzip-komprimierten Daten, die es ermöglichen, Sie zu suchen, um in einem Programm bewusst, dass zusätzliche Informationen zur Verfügung. Während es existiert in der standard-Vanille
gzip
nicht solche Marker entweder standardmäßig oder durch option.Dateien komprimiert, durch diese random-access-freundliche utilities sind etwas größer (vielleicht 2-20%) aufgrund der Marker selbst, sondern voll und ganz unterstützen Dekompression mit
gzip
oder einem anderen Dienstprogramm, das nichts von diesen Marken.Können Sie mehr erfahren in dieser Frage zu random access in verschiedenen Kompressions-Formate.
Es gibt auch eine "Gestrahlt Bioinformatik" blog von Peter Hahn mit mehreren posts zu diesem Thema, einschließlich:
Experimente mit
xz
xz
(ein LZMA - Kompressions-format) hat tatsächlich random-access-Unterstützung auf einer pro-block-Ebene, aber Sie werden nur einen einzigen block mit den Standardeinstellungen.Erstellung der Datei
xz
verketten können mehrere Archive zusammen, in welchem Fall jedes Archiv hat Ihren eigenen block. Die GNUsplit
kann dies leicht tun:Dieser erzählt
split
zu brechenbig.log
in 50MB Teile (vor Kompression), und führen Sie jeweils durchxz -c
, die Ausgänge der komprimierten chunk auf der standard-Ausgabe. Wir sammeln Sie dann, dass die standard-Ausgabe in eine einzelne Datei namensbig.log.sp.xz
.Dies zu tun, ohne GNU, brauchen Sie einen loop:
Analyse
Können Sie die Liste der block-offsets mit
xz --verbose --list FILE.xz
. Wenn Sie möchten, dass der Letzte block, müssen Sie die komprimierte Größe (Spalte 5) zuzüglich 36 bytes für den overhead (gefunden durch den Vergleich der Größe zuhd big.log.sp0.xz |grep 7zXZ
). Hol-block mittail -c
und Rohr, die durchxz
. Da die oben genannten Frage möchte die Letzte Zeile der Datei, die ich dann Pfeife, die durchtail -n1
:Seite Hinweis
Version 5.1.1 wurde die Unterstützung für die
--block-size
Flagge:Aber ich habe nicht in der Lage zu extrahieren, die eine bestimmte blockieren, da es sich nicht um vollständige Header zwischen den Blöcken. Ich vermute, dass dies nicht trivial ist, zu tun, von der Befehlszeile aus.
Experimente mit
gzip
gzip
unterstützt auch die Verkettung. Ich (kurz) versucht, imitiert diesen Vorgang fürgzip
ohne Glück.gzip --verbose --list
nicht genug Informationen geben, und es erscheint der Header sind zu variabel, zu finden.Dies würde erfordern das hinzufügen sync-flush Punkte, und da Ihre Größe variiert von der Größe des letzten Puffers in der vorherigen Kompression, das ist zu schwer zu tun auf der Kommandozeile (verwenden Sie dictzip oder einem anderen der zuvor besprochenen tools).
Habe ich
apt-get install dictzip
und spielte mit dictzip, aber nur ein wenig. Es funktioniert nicht ohne Argumente, die Schaffung eines (massiven!).dz
Archiv, die wederdictunzip
nochgunzip
verstehen konnte.Experimente mit
bzip2
bzip2
hat Kopfzeilen, die wir finden können. Das ist noch ein bisschen chaotisch, aber es funktioniert.Erstellung
Dies ist nur, wie die
xz
Verfahren oben:Sollte ich beachten Sie, dass dies deutlich langsamer als
xz
(48 min für bzip2 vs 17 min für xz vs 1 min fürxz -0
) als auch deutlich größere (97M für bzip2 vs 25M fürxz -0
vs 15M für xz), zumindest für meine test-log-Datei.Analyse
Dies ist ein wenig schwieriger, weil wir nicht in der schönen index. Wir haben zu erraten, wohin Sie gehen, und wir haben zu irren auf der Seite Scannen zu viel, aber mit eine riesige Datei, wir würden immer noch sparen-I/O.
Meine Vermutung für diesen test wurde 50000000 (aus dem original-52428800 gesetzt, eine pessimistische denke, das ist nicht pessimistisch genug für z.B. einen H. 264-Film.)
Diese nimmt nur die letzten 50 Millionen bytes, findet die binary offset des letzten BZIP2-header, subtrahiert, die aus der guess Größe, und zieht, dass viele bytes vom Ende der Datei. Nur das Teil ist entpackt und geworfen in
tail
.Werden, denn dies hat zur Abfrage der komprimierten Datei zweimal, und hat eine extra scan (die
grep
Aufruf sucht die header, die untersucht, das ganze erraten Platz), dies ist eine suboptimale Lösung. Siehe auch den folgenden Abschnitt über, wie langsambzip2
wirklich ist.Perspektive
Gegeben, wie schnell
xz
ist, es ist einfach das beste Wette; mit seiner schnellsten option (xz -0
) ist Recht schnell zu komprimieren oder zu Dekomprimieren und erstellt eine kleinere Datei alsgzip
oderbzip2
auf die log-Datei, ich wurde getestet mit. Andere tests (sowie verschiedene online-Quellen) deuten darauf hin, dassxz -0
vorzuziehen istbzip2
in allen Szenarien.Timing-tests wurden nicht umfassend ist, habe ich nicht Durchschnitt etwas und disk-caching verwendet wurde. Noch, Sie sehen richtig, es ist eine sehr kleine Menge von overhead aus
split
plus starten 145 Kompression Instanzen und nicht nur eins (dies kann sogar eine Netto - gewinnen, wenn es ermöglicht eine ansonsten nicht-Multithread-Dienstprogramm zu verbrauchen mehrere threads).dictzip -t file.dz
(einfache header-Prüfung): es wird entweder sofort fehlschlägt oder sofort gelingt.Gut, können Sie Zugang zufällig eine Gzip-Datei, wenn Sie zuvor erstellt eine index für jede Datei ...
Habe ich entwickeln ein Kommandozeilen-tool, das erzeugt Indizes für gzip-Dateien, die es ermöglichen, sehr schnelle random-access-innen Sie:
https://github.com/circulosmeos/gztool
Das tool verfügt über zwei Optionen, die von Interesse sein könnten für Sie:
$ gztool -t foo.gz | tail -1
Bitte beachten Sie, dass, wenn der index nicht existiert, wird diese verbrauchen die gleiche Zeit wie eine komplette Dekompression: aber als der index, ist wiederverwendbar, neben Recherchen werden erheblich reduziert, im Zeit!
Dieses tool basiert auf zran.c Demo-code von der original-zlib, so gibt es keine out-of-the-rules Magie!