GNU/Linux >> Tutoriales Linux >  >> Linux

Combinar por fecha varios archivos de registro que también incluyen líneas sin fecha (por ejemplo, seguimientos de pila)

Difícil. Si bien es posible usando date y matrices bash, este es realmente el tipo de cosa que se beneficiaría de un lenguaje de programación real. En Perl, por ejemplo:

$ 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

Aquí está lo mismo sin condensar en un guión comentado:

#!/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}";
}

Tenga en cuenta que esto supone que todas las líneas de fecha y solo las líneas de fecha contienen una coma. Si ese no es el caso, puede usar esto en su lugar:

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

El enfoque anterior necesita mantener todo el contenido de los archivos en la memoria. Si eso es un problema, aquí hay uno que no:

$ 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

Este simplemente coloca todas las líneas entre marcas de tiempo sucesivas en una sola línea al reemplazar las líneas nuevas con \0 (si esto puede estar en sus archivos de registro, use cualquier secuencia de caracteres que sepa que nunca estará allí). Esto pasó a sort y luego tr para recuperar las líneas.

Como señaló muy correctamente el OP, todas las soluciones anteriores deben recurrirse y no tener en cuenta que los archivos se pueden fusionar. Aquí hay uno que lo hace pero que, a diferencia de los demás, solo funcionará en dos archivos:

$ 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'

Y si guarda el comando perl como un alias, puede obtener:

$ 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. 20 archivos de registro de Linux que se encuentran en el directorio /var/log

  2. Contar líneas en archivos grandes

  3. Sintaxis del archivo de configuración logrotate:¿son posibles múltiples entradas comodín?

  4. Cambie el nombre de varios archivos para eliminar el sufijo común de los nombres de archivo

  5. Cola múltiples archivos remotos

Cómo combinar varios archivos PDF en un solo PDF en Linux

Cómo unir/combinar varios archivos de audio en uno solo en Linux

¿Comando para limpiar archivos de registro antiguos?

archivos de registro de Linux

10 impresionantes ejemplos para ver enormes archivos de registro en Unix

3 métodos para ver la salida tail -f de múltiples archivos de registro en una terminal