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

Jac*_*nor 23 journalctl

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

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

Ela*_*ich 17

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

获取单元的最新调用 ID

$ systemctl show --value -p InvocationID openipmi
bd3eb84c3aa74169a3dcad2af183885b
Run Code Online (Sandbox Code Playgroud)

要获取最近调用的日志,例如,openipmi,无论是否失败,您都可以使用 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.
Run Code Online (Sandbox Code Playgroud)

(请注意,--value自 以来可用systemd 230,早于InvocationID


小智 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}')"
Run Code Online (Sandbox Code Playgroud)


Nik*_*tis 5

您可以使用启动标志仅从该启动中获取日志。例如

journalctl _SYSTEMD_UNIT=avahi-daemon.service -b 5
Run Code Online (Sandbox Code Playgroud)

  • 这与我想要的类似,但它在以下情况下不起作用:1)如果自上次服务运行以来机器已重新启动,或2)如果自上次启动以来服务已运行多次。 (3认同)

Bre*_*ign 5

这些可能对您有帮助:

  • 日志控制-u foo.service | 尾部-n 2

    或将2替换为预期行数

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

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


小智 5

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

journalctl _PID=1234
Run Code Online (Sandbox Code Playgroud)

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

journalctl --fields --unit kubelet
Run Code Online (Sandbox Code Playgroud)

一个可用字段是_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
Run Code Online (Sandbox Code Playgroud)

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