zgrep tgz recursive extraer descomprimir como archivos bash shell logging grep

bash - tgz - tar gz windows



Cómo agregar zgrep a la última línea de un archivo gz sin cola (1)

Aquí está mi problema, tengo un conjunto de grandes archivos de registro gz , la primera información en la línea es un texto de fecha y hora, por ejemplo: 2014-03-20 05:32:00.

Necesito comprobar qué conjunto de archivos de registro contiene datos específicos. Para el init simplemente hago un:

''-query-data-'' zgrep -m 1 ''^20140320-04'' 20140320-0{3,4}*gz

PERO CÓMO hacer lo mismo con la última línea sin procesar todo el archivo como se haría con zcat (demasiado pesado):

zcat foo.gz | tail -1

Información adicional, esos registros se crean con la hora de datos de su registro inicial, por lo que si quiero consultar los registros a las 14:00:00 tengo que buscar, también, en los archivos creados ANTES de las 14:00:00, como lo haría un archivo se creará a las 13:50:00 y se cerrará a las 14:10:00.


La solución más fácil sería alterar su rotación de registros para crear archivos más pequeños.

La segunda solución más fácil sería usar una herramienta de compresión que admita el acceso aleatorio.

Los proyectos como dictzip , BGZF y csio agregan puntos de descarga de sincronización en varios intervalos dentro de los datos comprimidos gzip que le permiten buscar en un programa que tenga en cuenta esa información adicional. Si bien existe en el estándar, el gzip vainilla no agrega dichos marcadores ya sea por defecto o por opción.

Los archivos comprimidos por estas utilidades amigables al acceso aleatorio son ligeramente más grandes (quizás un 2-20%) debido a los marcadores en sí mismos, pero admiten completamente la descompresión con gzip u otra utilidad que no conoce estos marcadores.

Puede obtener más información sobre esta cuestión sobre el acceso aleatorio en varios formatos de compresión .

También hay un blog de "Blasted Bioinformatics" de Peter Cock con varias publicaciones sobre este tema, que incluyen:

Experimentos con xz

xz (un formato de compresión LZMA ) en realidad tiene soporte de acceso aleatorio en un nivel por bloque, pero solo obtendrá un bloque único con los valores predeterminados.

Creación de archivo

xz puede concatenar múltiples archivos juntos, en cuyo caso cada archivo tendría su propio bloque. La split GNU puede hacer esto fácilmente:

split -b 50M --filter ''xz -c'' big.log > big.log.sp.xz

Esto le dice a split que split big.log en fragmentos de 50MB ( antes de la compresión) y ejecute cada uno a través de xz -c , que envía el fragmento comprimido a la salida estándar. Luego recogemos esa salida estándar en un solo archivo llamado big.log.sp.xz

Para hacer esto sin GNU, necesitarías un bucle:

split -b 50M big.log big.log-part for p in big.log-part*; do xz -c $p; done > big.log.sp.xz rm big.log-part*

Parsing

Puede obtener la lista de compensaciones de bloque con xz --verbose --list FILE.xz Si desea el último bloque, necesita su tamaño comprimido (columna 5) más 36 bytes para gastos generales (se encuentra al comparar el tamaño con hd big.log.sp0.xz |grep 7zXZ ). Trae ese bloque usando la tail -c y la tubería que atraviesa xz . Dado que la pregunta anterior quiere la última línea del archivo, luego tail -n1 eso a través de la tail -n1 :

SIZE=$(xz --verbose --list big.log.sp.xz |awk ''END { print $5 + 36 }'') tail -c $SIZE big.log.sp.xz |unxz -c |tail -n1

Nota al margen

La versión 5.1.1 introdujo el soporte para el --block-size :

xz --block-size=50M big.log

Sin embargo, no he podido extraer un bloque específico ya que no incluye encabezados completos entre bloques. Sospecho que esto no es trivial para hacer desde la línea de comando.

Experimentos con gzip

gzip también admite la concatenación. Yo (brevemente) intenté imitar este proceso para gzip sin suerte. gzip --verbose --list no proporciona suficiente información y parece que los encabezados son demasiado variables para encontrarlos.

Esto requeriría agregar puntos de descarga de sincronización, y dado que su tamaño varía según el tamaño del último búfer en la compresión anterior, eso es demasiado difícil de hacer en la línea de comando (use dictzip u otra de las herramientas analizadas anteriormente).

Hice apt-get install dictzip y jugué con dictzip, pero solo un poco. No funciona sin argumentos, creando un archivo .dz (masivo!) .dz ni dictunzip ni gunzip pueden entender.

Experimentos con bzip2

bzip2 tiene encabezados que podemos encontrar. Esto todavía es un poco complicado, pero funciona.

Creación

Esto es como el procedimiento xz anterior:

split -b 50M --filter ''bzip2 -c'' big.log > big.log.sp.bz2

Debo señalar que esto es considerablemente más lento que xz (48 min para bzip2 frente a 17 min para xz frente a 1 min para xz -0 ) y considerablemente más grande (97 M para bzip2 frente a 25M para xz -0 frente a 15M para xz), en menos para mi archivo de registro de prueba.

Parsing

Esto es un poco más difícil porque no tenemos el buen índice. Tenemos que adivinar a dónde ir, y tenemos que equivocarnos demasiado escaneando, pero con un archivo masivo, aún ahorraríamos E / S.

Mi conjetura para esta prueba fue 50000000 (fuera de la original 52428800, una suposición pesimista que no es lo suficientemente pesimista como, por ejemplo, una película H.264).

GUESS=50000000 LAST=$(tail -c$GUESS big.log.sp.bz2 / |grep -abo ''BZh91AY&SY'' |awk -F: ''END { print ''$GUESS''-$1 }'') tail -c $LAST big.log.sp.bz2 |bunzip2 -c |tail -n1

Esto toma solo los últimos 50 millones de bytes, encuentra el desplazamiento binario del último encabezado BZIP2, lo resta del tamaño de adivinar y saca esos muchos bytes del final del archivo. Solo esa parte se descomprime y se arroja a la tail .

Como esto tiene que consultar el archivo comprimido dos veces y tiene un escaneo adicional (la llamada grep busca el encabezado, que examina todo el espacio adivinado), esta es una solución subóptima. Consulte también la sección a continuación sobre qué tan lento es realmente bzip2 .

Perspectiva

Dado lo rápido que es xz , es la mejor opción; usar su opción más rápida ( xz -0 ) es bastante rápida para comprimir o descomprimir y crea un archivo más pequeño que gzip o bzip2 en el archivo de registro con el que estaba probando. Otras pruebas (así como varias fuentes en línea) sugieren que xz -0 es preferible a bzip2 en todos los escenarios.

————— No Random Access —————— ——————— Random Access ——————— FORMAT SIZE RATIO WRITE READ SIZE RATIO WRITE SEEK ————————— ————————————————————————————— ————————————————————————————— (original) 7211M 1.0000 - 0:06 7211M 1.0000 - 0:00 bzip2 96M 0.0133 48:31 3:15 97M 0.0134 47:39 0:00 gzip 79M 0.0109 0:59 0:22 dictzip 605M 0.0839 1:36 (fail) xz -0 25M 0.0034 1:14 0:12 25M 0.0035 1:08 0:00 xz 14M 0.0019 16:32 0:11 14M 0.0020 16:44 0:00

Las pruebas de tiempo no fueron exhaustivas, no promedié nada y el almacenamiento en caché de disco estaba en uso. Aún así, se ven correctos; hay una cantidad muy pequeña de sobrecarga desde split más el lanzamiento de 145 instancias de compresión en lugar de solo una (esto incluso puede ser una ganancia neta si permite que una utilidad que no sea multihilo consuma múltiples hilos).