Correlacionar / var / log / * marcas de tiempo

20

/var/log/messages, /var/log/syslogy algunos otros archivos de registro usan una marca de tiempo que contiene un tiempo absoluto, como Jan 13 14:13:10.

/var/log/Xorg.0.logy /var/log/dmesg, además de la salida de $ dmesg, use un formato que se vea como

[50595.991610] malkovich: malkovich malkovich malkovich malkovich

Supongo que los números representan segundos y microsegundos desde el inicio.

Sin embargo, mi intento de correlacionar estos dos conjuntos de marcas de tiempo (usando la salida de uptime) dio una discrepancia de aproximadamente 5000 segundos.

Esta es aproximadamente la cantidad de tiempo que mi computadora estuvo suspendida.

¿Hay una manera conveniente de asignar las marcas de tiempo numéricas utilizadas por dmesg y Xorg en marcas de tiempo absolutas?

actualizar

Como un paso preliminar para resolver esto, y también para que mi pregunta sea un poco más clara, he escrito un script de Python para analizar /var/log/syslogy generar el sesgo de tiempo. En mi máquina, ejecutando ubuntu 10.10, ese archivo contiene numerosas líneas originadas en el núcleo que están estampadas con la marca de tiempo dmesg y la marca de tiempo syslog. El script genera una línea para cada línea en ese archivo que contiene una marca de tiempo del núcleo.

Uso:

python syslogdriver.py /var/log/syslog | column -nts $'\t'

Salida expurgada (ver abajo para las definiciones de columna):

abs              abs_since_boot  rel_time      rel_offset  message
Jan 13 07:49:15  32842.1276569   32842.301498  0           malkovich malkovich

... rel_offsetes 0 para todas las líneas intermedias ...

Jan 13 09:55:14  40401.1276569   40401.306386  0           PM: Syncing filesystems ... done.
Jan 13 09:55:14  40401.1276569   40401.347469  0           PM: Preparing system for mem sleep
Jan 13 11:23:21  45688.1276569   40402.128198  -5280       Skipping EDID probe due to cached edid
Jan 13 11:23:21  45688.1276569   40402.729152  -5280       Freezing user space processes ... (elapsed 0.03 seconds) done.
Jan 13 11:23:21  45688.1276569   40402.760110  -5280       Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done.
Jan 13 11:23:21  45688.1276569   40402.776102  -5280       PM: Entering mem sleep

... rel_offsetes -5280 para todas las líneas restantes ...

Jan 13 11:23:21  45688.1276569   40403.149074  -5280       ACPI: Preparing to enter system sleep state S3
Jan 13 11:23:21  45688.1276569   40403.149477  -5280       PM: Saving platform NVS memory
Jan 13 11:23:21  45688.1276569   40403.149495  -5280       Disabling non-boot CPUs ...
Jan 13 11:23:21  45688.1276569   40403.149495  -5280       Back to C!
Jan 13 11:23:21  45688.1276569   40403.149495  -5280       PM: Restoring platform NVS memory
Jan 13 11:23:21  45688.1276569   40403.151034  -5280       ACPI: Waking up from system sleep state S3

... Las líneas finales son un poco más abajo, aún muy por encima del final de la salida. Algunos de ellos presumiblemente se escribieron en dmesgel búfer circular antes de que ocurriera la suspensión, y solo se propagaron syslogdespués. Esto explica por qué todos ellos tienen la misma marca de tiempo de syslog.

Definiciones de columna:

abs es el tiempo registrado por syslog.

abs_since_bootes el mismo tiempo en segundos desde el inicio del sistema, basado en el contenido /proc/uptimey el valor de time.time().

rel_time es la marca de tiempo del kernel.

rel_offsetes la diferencia entre abs_since_booty rel_time. Estoy redondeando esto a las decenas de segundos para evitar errores syslogúnicos debido a que las marcas de tiempo absolutas (es decir, generadas) solo tienen precisión de segundos. En realidad, esa no es la forma correcta de hacerlo, ya que realmente (creo que ...) solo da como resultado una menor posibilidad de tener un error de 10 por 10. Si alguien tiene una idea mejor, hágamelo saber.

También tengo algunas preguntas sobre el formato de fecha de syslog; en particular, me pregunto si alguna vez aparece un año en él. Supongo que no, y en cualquier caso probablemente podría ayudarme a mí mismo con esa información en TFM, pero si alguien sabe que sería útil. Suponiendo, por supuesto, que alguien use este script en algún momento en el futuro, en lugar de simplemente romper un par de líneas de código Perl.

Próximo:

Por lo tanto, a menos que una de ustedes me dé una revelación bienvenida, mi próximo paso será agregar una función para obtener el sesgo de tiempo para una marca de tiempo del núcleo dado. Debería poder alimentar el script uno o un conjunto de syslogs, junto con una marca de tiempo del núcleo, para obtener una marca de tiempo absoluta. Entonces puedo volver a depurar mis problemas de Xorg, que se me escapan en este momento.

intuido
fuente
1
Creo que esto califica como un error y debería informarse. Por cierto, syslog-ng usa marcas de tiempo sensatas con las que puede ordenar sort, tener año, zona horaria, etc. +1 para el script de Python.
stribika
@stribika: ¿sería un problema de kernel o un problema de syslog? ¿O ambos? Parece que syslog necesita ser notificado de que el sistema ha sido suspendido ... tal vez podría hacerlo por sí mismo con suspender y reanudar ganchos.
intuido
Para mí, parece que el núcleo tiene la culpa. Los valores rel_time no "omiten" el tiempo mientras el sistema estaba suspendido. Sin embargo, me parece extraño que el sesgo comience antes de que suceda la suspensión. Los valores ya están equivocados para lo Freezing user space processescual se hace claramente antes de dormir.
Stribika
2
@stribika: Mi teoría de trabajo al respecto es que esos eventos no se envían a syslog hasta después del currículum, porque ocurren después de que se haya suspendido syslog.
intuido
@stribika: Además, tiene razón acerca de que el núcleo está "en falta": según tengo entendido (después de reconsiderarlo), syslog simplemente antepone la marca de tiempo absoluta al texto (comenzando con [12345.6789]..) emitido por el núcleo, por lo que está haciendo las cosas correctamente , sujeto a los problemas abordados por mi último comentario. No estoy seguro de qué debería hacer realmente el núcleo aquí; depende de lo que esas marcas de tiempo relativas al inicio están destinadas a indicar. El tiempo de ejecución (en oposición al tiempo desde el arranque) puede ser significativo en algunos contextos. Supongo que idealmente habría un registro confiable de ambos valores.
intuido

Respuestas:

4

Problema interesante, no estoy seguro de que alguna vez haya intentado hacer esto. Pero he notado la marca de tiempo de la que está hablando y siempre he creído que son segundos desde el arranque.

En mi syslog que tengo en mi servidor, tengo:

Jan 10 19:58:55 wdgitial kernel: [    0.000000] Initializing cgroup subsys cpuset
Jan 10 19:58:55 wdgitial kernel: [    0.000000] Initializing cgroup subsys cpu
Jan 10 19:58:55 wdgitial kernel: [    0.000000] Linux version 2.6.32-21-server (buildd@yellow) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) ) #32-Ubuntu SMP Fri Apr 16     09:17:34 UTC 2010 (Ubuntu 2.6.32-21.32-server 2.6.32.11+drm33.2)
Jan 10 19:58:55 wdgitial kernel: [    0.000000] Command line:  root=/dev/xvda1 ro quiet splash

Me imagino que esto es bastante consistente entre la mayoría de las distribuciones de Linux, ya que este es el núcleo que escupe sus cosas.

Y aquí tengo la fecha junto con la marca de tiempo.

Ryan Gibbons
fuente
3

Puedes probar esto:

Primero, obtenga la marca de tiempo del archivo dmesg (supongo que este será el tiempo 0 de dmesg). Usarás

ls -l --time-style = +% s

/var/log$ ls -l --time-style=+%s dmesg
-rw-r----- 1 root adm 56181 1294941018 dmesg

Puede convertir los segundos en una fecha legible para humanos con

perl -e 'print scalar localtime(1294941018)' 

Entonces, para ver un tiempo de evento legible, agregue los segundos del evento en dmesg. Si el evento dmesg fue de 55.290387 segundos, agregue 55 o 55.290387:

perl -e 'print scalar localtime(1294953978 + 55)'

Otra forma de transformar los segundos arraigados en época en tiempo legible es usar date -d como se sugiere. Si le dice a 'fecha' que represente una hora provista con -d, puede indicar que la hora a convertir está en segundos desde la época usando @.

date -d "@1294953978"

Esto le da algo como "Jue 13 de enero 15:26:18 CST 2011" como salida.

fecha +% s
imprimirá la hora actual en el formato de segundos desde la época.

No recuerdo cómo hacer matemática de shell, por lo que generalmente uso el método perl como se indicó anteriormente. :)

belacqua
fuente
1
@jgbelacqua: Quieres date -d @$((1294953978 + 55)), al menos bajo bash. Sin embargo, algunas marcas de tiempo del núcleo están sesgadas, lo que significa que los tiempos producidos por este método serían anteriores a sus marcas de tiempo correspondientes /var/log/syslog. Parece que esto sucede como resultado de los eventos de suspensión a RAM, presumiblemente además de la hibernación y posiblemente otras cosas, porque el tiempo del núcleo no se incrementa durante esos períodos. Vea la actualización de la pregunta para más información.
intuido
2

La forma más fácil de asignar el número de dmesg a una fecha es usar el dateprograma.

date -d "-50595 seconds"

Este comando muestra la fecha de la hora actual menos 50595 segundos.

De man date:

-d, --date=STRING
       display time described by STRING, not `now'

El número es igual al tiempo de encendido, no al tiempo transcurrido desde el momento del arranque.

Lekensteyn
fuente
2

Dado que notó el cambio de la inclinación del tiempo durante la suspensión / reanudación, notaré que esto está documentado en al menos un lugar. La página del comando man dmesg (1) dice:

La fuente de tiempo utilizada para los registros no se actualiza después del sistema SUSPENDER / REANUDAR.

No pude encontrar una manera de hacer que el núcleo mantenga estas marcas de tiempo sincronizadas con el tiempo de la pared.

Andrés
fuente
1

Rápido, sucio, funciona.

$ dmesg | grep 3w | perl /root/print_time_offset.pl

Contenido de ese guión:

$ cat /root/print_time_offset.pl

#!/usr/bin/perl

$uptime = `cat /proc/uptime | awk '{print $1}';`;
$boot = time() - $uptime;
chomp $boot;
while (<STDIN>) {
        if ($_ =~ /^\[([\s\d\.]+)\]/) {
                $time_offset = $1;
        }
        $real_time = sprintf scalar localtime($boot + $time_offset);
        $_ =~ s/\[[\s\d\.]+\]/\[$real_time\]/;
        print $_;
}

La salida de muestra es la siguiente:

[Mon Feb 21 23:06:33 2011] 3ware 9000 Storage Controller device driver for Linux v2.26.02.012.
[Mon Feb 21 23:06:33 2011] 3w-9xxx 0000:03:00.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[Mon Feb 21 23:06:33 2011] 3w-9xxx 0000:03:00.0: setting latency timer to 64
[Mon Feb 21 23:06:33 2011] scsi4 : 3ware 9000 Storage Controller
[Mon Feb 21 23:06:33 2011] 3w-9xxx: scsi4: Found a 3ware 9000 Storage Controller at 0xfbcde000, IRQ: 16.
[Mon Feb 21 23:06:34 2011] 3w-9xxx: scsi4: Firmware FE9X 4.08.00.006, BIOS BE9X 4.08.00.001, Ports: 4.
[Mon Feb 21 23:06:35 2011] 3w-9xxx: scsi4: ERROR: (0x03:0x0101): Invalid command opcode:opcode=0x85.
[Mon Feb 21 23:06:35 2011] 3w-9xxx: scsi4: ERROR: (0x03:0x0101): Invalid command opcode:opcode=0x85.
[Mon Feb 21 23:06:35 2011] 3w-9xxx: scsi4: ERROR: (0x03:0x0101): Invalid command opcode:opcode=0x85.
[Mon Feb 21 23:06:35 2011] 3w-9xxx: scsi4: ERROR: (0x03:0x0101): Invalid command opcode:opcode=0x85.
[Mon Feb 21 23:06:35 2011] 3w-9xxx: scsi4: ERROR: (0x03:0x0101): Invalid command opcode:opcode=0x85.
[Mon Feb 21 23:06:35 2011] 3w-9xxx: scsi4: ERROR: (0x03:0x0101): Invalid command opcode:opcode=0x85.
[Sat Feb 26 02:01:01 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x0029): Verify started:unit=0, subunit=1.
[Sat Feb 26 02:01:01 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x0029): Verify started:unit=0, subunit=0.
[Sat Feb 26 16:49:13 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x002B): Verify completed:unit=0, subunit=1.
[Sat Feb 26 17:07:19 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x002B): Verify completed:unit=0, subunit=0.
[Sat Mar  5 02:00:16 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x0029): Verify started:unit=0, subunit=1.
[Sat Mar  5 02:00:16 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x0029): Verify started:unit=0, subunit=0.
[Sat Mar  5 18:48:57 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x002B): Verify completed:unit=0, subunit=1.
[Sat Mar  5 19:05:17 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x002B): Verify completed:unit=0, subunit=0.
[Sat Mar 12 02:00:30 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x0029): Verify started:unit=0, subunit=1.
[Sat Mar 12 02:00:30 2011] 3w-9xxx: scsi4: AEN: INFO (0x04:0x0029): Verify started:unit=0, subunit=0.
Dacav
fuente
1
Supongo que solo leyó los primeros párrafos de la pregunta. Compruébalo de nuevo con más detalle. O, alternativamente, intente suspender su computadora y verificar si su secuencia de comandos informa correctamente las marcas de tiempo absolutas de los mensajes recién registrados.
intuido