¿Hay alguna manera de hacer que journalctl muestre registros de "la última vez que se ejecutó foo.service"?


15

Estoy particularmente interesado en esto para ver la salida de los servicios de un solo disparo que se ejecutan en un temporizador. La --unitbandera está cerca, pero concatena todas las ejecuciones del servicio juntas. La forma más obvia en la que puedo pensar sería filtrar el PID, pero eso me preocupa por la reutilización de PID / servicios que se bifurcan, y obtener el último PID es bastante inconveniente. ¿Hay algún otro identificador que corresponda a una sola ejecución de un servicio que pueda usar para filtrar los registros?

EDITAR: Me encantaría aceptar un "no" autorizado si esa es la respuesta real.

Respuestas:


6

Desde la systemdversión 232, tenemos el concepto de ID de invocación. Cada vez que se ejecuta una unidad, tiene una ID de invocación única de 128 bits. A diferencia de lo MainPIDque puede reciclarse o lo ActiveEnterTimestampque puede tener problemas de resolución, es una forma segura de obtener todo el registro de una invocación de unidad del sistema en particular.

Para obtener la última identificación de invocación de una unidad

$ systemctl show --value -p InvocationID openipmi
bd3eb84c3aa74169a3dcad2af183885b

Para obtener el diario de la última invocación de, por ejemplo openipmi, si falló o no, puede usar el one liner

$ journalctl _SYSTEMD_INVOCATION_ID=`systemctl show -p InvocationID --value openipmi.service`
-- Logs begin at Thu 2018-07-26 12:09:57 IDT, end at Mon 2019-07-08 01:32:50 IDT. --
Jun 21 13:03:13 build03.lbits openipmi[1552]:  * Starting ipmi drivers
Jun 21 13:03:13 build03.lbits openipmi[1552]:    ...fail!
Jun 21 13:03:13 build03.lbits openipmi[1552]:    ...done.

(Tenga en cuenta que --valueestá disponible desde systemd 230, anterior a InvocationID)


Si alguien intenta investigar esto: journalctl --user -u UNITFILE -f -o json-prettypodría ser útil; Estás buscando MESSAGEcampos en particular. Descubrí que es posible que también lo necesite USER_INVOCATION_ID, y que algunos mensajes no tienen ninguna identificación de invocación adjunta, por lo que no se pueden filtrar a través de este mecanismo. No estoy seguro de por qué, tal vez mi registro está mal configurado ..
karlicoss

14

No estoy seguro de qué marca de tiempo tiene más sentido, pero esto funciona para mí. Esperemos que haya una mejor manera de trabajar con las marcas de tiempo de systemctl showawk: no se pudo encontrar la forma de controlar el formato de las marcas de tiempo.

unit=foo.service

ts=$(systemctl show -p ActiveEnterTimestamp $unit)

echo $ts
ActiveEnterTimestamp=Fri 2016-11-11 12:30:01 MST

journalctl -u $unit --since "$(echo $ts | awk '{print $2 $3}')"

En caso de que alguien lo necesite como una línea: journalctl --since " systemctl show -p ActiveEnterTimestamp thermo.service | awk '{print $2 \" \" $3}'" -fu thermo.service | menos
DimanNe

También puede usar systemctl show -p ActiveEnterTimestamp --value $unit, por lo que no hay necesidad de awk extra
karlicoss

4

Puede usar el indicador de arranque para obtener solo los registros de ese arranque. por ejemplo

journalctl _SYSTEMD_UNIT=avahi-daemon.service -b 5

2
Esto es similar a lo que quiero, pero no funciona en situaciones como: 1) si la máquina se ha reiniciado desde la última vez que se ejecutó el servicio, o 2) si el servicio se ha ejecutado varias veces desde el último inicio.
Jack O'Connor

No estoy seguro de por qué no funciona para el primer caso. Si se ha reiniciado, también se reiniciará. Solo tienes que ir a ese arranque específico y buscar tu información. Con respecto al segundo ... tienes razón. Los registros de ruido dependen de la cantidad de veces que se reinició el servicio. Pero una vez que haya detectado su servicio pid, puede filtrarlo utilizando el argumento _PID = XXX. Las posibilidades de reutilizar el mismo pid para el mismo servicio en el mismo ciclo de arranque son ..... ni idea ... sino casi imposibles.
Nikolaidis Fotis

Estoy interesado en manejar servicios que no necesariamente se ejecutan en el arranque, ya sea porque están en temporizadores o porque son comandos únicos.
Jack O'Connor

3

Estos pueden ayudarte:

  • journalctl -u foo.service | cola -n 2

    o reemplace 2 con el número esperado de líneas

  • journalctl -u foo.service --since = ' 2016-04-11 13:00:00 '

También puede combinarlos para obtener en primer lugar la última marca de tiempo de tiempo de ejecución, y luego usar esa marca de tiempo con el modificador --since.


Esto parece una solución similar al enfoque PID, pero es muy manual. Si mi servicio se ejecuta durante muchos segundos y escupe muchas líneas de registro, tengo que buscar la primera línea que tiene la marca de tiempo de inicio que me interesa. Eso no funcionará muy bien en un guión.
Jack O'Connor

3

Puede usar filtros de campo con Journalctl. P.ej

journalctl _PID=1234

Obtenga una lista de todos los campos disponibles usando:

journalctl --fields --unit kubelet

Un campo disponible es _PID.

Puede obtener el PID de un proceso en ejecución usando pidofosystemctl show --property MainPID <SERVICE_NAME>

Así es como obtengo los registros del proceso actual de Kubenetes kubelet:

# journalctl --unit kubelet _PID=$(systemctl show --property MainPID kubelet 2>/dev/null | cut -d= -f2) | head

Ahora dime por qué Kubernetes es tan difícil de instalar :-(


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.