有没有办法使journalctl显示“上次运行foo.service”的日志?


16

我对查看计时器上运行的oneshot服务的输出特别感兴趣。该--unit标志是关闭的,但是它将所有服务运行串联在一起。我能想到的最明显的方法是对PID进行过滤,但这使我担心分叉的PID重用/服务,并且获取最后一个PID非常不便。是否有一些其他标识符可以与服务的单次运行相对应,可以用来过滤日志?

编辑:如果这是真正的答案,我会很乐意接受权威的“否”。

Answers:


8

systemdversion开始232,我们有了调用ID的概念。每次运行一个单元时,它都有一个唯一的128位调用ID。与MainPID可以回收或ActiveEnterTimestamp有解决问题的方法不同,它是获取特定systemd单元调用的所有日志的故障保护方法。

获取单元的最新调用ID

$ systemctl show --value -p InvocationID openipmi
bd3eb84c3aa74169a3dcad2af183885b

要获取最新调用(例如openipmi,是否失败)的日志,可以使用一个内衬

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

(请注意,--valuesystemd 230,早于可用InvocationID


1
如果有人试图对此进行调查:journalctl --user -u UNITFILE -f -o json-pretty可能会有所帮助;您正在MESSAGE特别寻找字段。我发现您可能还需要USER_INVOCATION_ID,而且某些消息没有附加任何调用ID,因此无法通过此机制进行过滤。不知道为什么,也许我的日志记录配置错误..
karlicoss

14

我不确定哪个时间戳最有意义,但这对我有用。希望有一种systemctl show比awk 更好的时间戳处理方法-无法弄清楚如何控制时间戳的格式。

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

以防万一有人需要它作为单行代码:journalctl-因为“ systemctl show -p ActiveEnterTimestamp thermo.service | awk '{print $2 \" \" $3}'” -fu thermo.service | 更少
DimanNe

您也可以使用systemctl show -p ActiveEnterTimestamp --value $unit,因此不需要额外的awk
karlicoss

4

您可以使用引导标志来仅从该引导中获取日志。例如

journalctl _SYSTEMD_UNIT=avahi-daemon.service -b 5

2
这与我想要的类似,但是在以下情况下不起作用:1)如果自上次运行服务以来已重新启动计算机,或2)自上次启动以来该服务已运行多次。
杰克·奥康纳

我不确定为什么在第一种情况下不起作用。如果已重新启动,则也会重新启动。您只需要转到该特定的启动并获取您的信息即可。关于第二个……你是对的。噪声日志取决于重新启动服务的次数。但是,一旦发现服务pid,就可以使用_PID = XXX参数对其进行过滤。在相同的启动周期中为相同的服务重用相同的pid的机会是……..不知道……但是几乎是不可能的。
Nikolaidis Fotis

我对处理不一定在启动时运行的服务感兴趣,这是因为它们在计时器上或因为它们是一次性命令。
杰克·奥康纳

4

这些可能会帮助您:

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

    或将2替换为预期的行数

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

您也可以将它们组合起来,以便首先获取上次运行时间的时间戳,然后将该时间戳与--since开关一起使用。


感觉就像是一种解决方案,类似于PID方法,但是非常手动。如果我的服务运行了许多秒,并且吐出了很多日志行,那么我必须去搜索具有我关心的开始时间戳的第一行。在脚本中不能很好地工作。
杰克·奥康纳

3

您可以将字段过滤器与Journalctl一起使用。例如

journalctl _PID=1234

使用以下命令获取所有可用字段的列表:

journalctl --fields --unit kubelet

一个可用的字段是_PID

您可以使用pidof或获取运行中进程的PIDsystemctl show --property MainPID <SERVICE_NAME>

所以这是我从当前Kubernetes kubelet进程中获取日志的方法:

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

现在告诉我为什么我这么难安装Kubernetes :-(


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.