Existe uma maneira de fazer o journalctl mostrar logs da "última vez em que foo.service foi executado"?


15

Estou particularmente interessado nisso por examinar a saída dos serviços oneshot executados em um timer. A --unitsinalização está próxima, mas concatena todas as execuções do serviço juntas. A maneira mais óbvia em que posso pensar seria filtrar o PID, mas isso me preocupa com a reutilização / serviços do PID que bifurcam, e obter o último PID é bastante inconveniente. Existe algum outro identificador que corresponda a uma única execução de um serviço, que eu poderia usar para filtrar os logs?

Edição: Eu aceitaria felizmente um "não" autoritário se essa for a resposta real.

Respostas:


6

Desde a systemdversão 232, temos o conceito de identificação de chamada. Cada vez que uma unidade é executada, ela possui um ID de chamada de 128 bits exclusivo. Diferente de MainPIDqual pode ser reciclado ou ActiveEnterTimestampque pode ter problemas de resolução, é uma maneira segura de obter todo o log de uma chamada de unidade do systemd específica.

Para obter o ID de chamada mais recente de uma unidade

$ systemctl show --value -p InvocationID openipmi
bd3eb84c3aa74169a3dcad2af183885b

Para obter o diário da última chamada de, digamos openipmi, se falhou ou não, você pode usar o liner único

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

(Observe que o --valueitem está disponível desde que systemd 230, mais antigo que InvocationID)


Se alguém está tentando investigar isso: journalctl --user -u UNITFILE -f -o json-prettypode ser útil; você está procurando MESSAGEcampos em particular. Descobri que você também pode precisar USER_INVOCATION_ID, e também algumas mensagens não têm nenhum ID de chamada anexado a elas, portanto, não podem ser filtradas por esse mecanismo. Não sei por que, talvez meu registro esteja mal configurado ..
— karlicoss 24/01

14

Não tenho certeza de qual carimbo de data / hora faz mais sentido, mas isso funciona para mim. Espero que exista uma maneira melhor de trabalhar com os registros de data e hora do systemctl showque o awk - não consegui descobrir como controlar o formato dos registros de data e hora.

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}')"

Apenas no caso de alguém precisar disso como uma linha: journalctl --since " systemctl show -p ActiveEnterTimestamp thermo.service | awk '{print $2 \" \" $3}'" -fu thermo.service | menos
— DimanNe 4/11

Você também pode usar systemctl show -p ActiveEnterTimestamp --value $unit, para que não seja necessário extra awk
— karlicoss

4

Você pode usar o sinalizador de inicialização para buscar apenas os logs dessa inicialização. por exemplo

journalctl _SYSTEMD_UNIT=avahi-daemon.service -b 5

2
Isso é semelhante ao que eu quero, mas não funciona em situações como: 1) se a máquina foi reinicializada desde a última vez em que o serviço foi executado, ou 2) se o serviço foi executado várias vezes desde a última inicialização.
— Jack O'Connor

Não sei por que não funciona no 1º caso. Se tiver sido reiniciado, também será reiniciado. Você só precisa ir a essa inicialização específica e buscar suas informações. Quanto ao segundo ... você está certo. Os logs de ruído dependem do número de vezes que o serviço foi reiniciado. Mas uma vez que você localizou seu serviço, pode filtrá-lo usando o argumento _PID = XXX. As chances de reutilizar o mesmo pid para o mesmo serviço no mesmo ciclo de inicialização são ..... nenhuma idéia ... mas quase impossível.
— Nikolaidis Fotis

Estou interessado em lidar com serviços que não necessariamente executam na inicialização, porque eles estão em timers ou porque são comandos únicos.
— Jack O'Connor

3

Isso pode ajudá-lo a:

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

    ou substitua 2 pelo número esperado de linhas

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

Você também pode combiná-los para obter primeiro o último registro de data e hora do tempo de execução e depois usá-lo com a opção --since.


Parece uma solução alternativa semelhante à abordagem PID, mas é muito manual. Se meu serviço for executado por muitos segundos e cuspir muitas linhas de log, tenho que procurar a primeira linha com o carimbo de data e hora de início que me interessa. Isso não funcionará muito bem em um script.
— Jack O'Connor

3

Você pode usar filtros de campo com o Journalctl. Por exemplo

journalctl _PID=1234

Obtenha uma lista de todos os campos disponíveis usando:

journalctl --fields --unit kubelet

Um campo disponível é _PID.

Você pode obter o PID de um processo em execução usando pidofousystemctl show --property MainPID <SERVICE_NAME>

Então, aqui está como eu obtenho os logs do processo atual do Kubernetes kubelet:

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

Agora me diga por que eu é tão difícil instalar o Kubernetes :-(


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.