我有一个记录到标准输出的 systemd 服务。从那里,systemd 捕获 STDOUT 并将其写入日志。
我使用一种常见的习惯用法来处理错误,其中我进行了echo
一些诊断,然后以非零错误代码退出:
echo "my final error";
exit 1;
我的问题是,这最后echo
一行出现在日记中,但与我的“单位”没有正确关联。通过查看journalctl -o json-pretty
,我可以看出有什么区别。最终日志记录缺少属性 _SYSTEMD_CGROUP 和 _SYSTEMD_UNIT。
我认为正在发生的是一种竞争条件。我怀疑 bash 脚本journald
在进入退出行之前不会等待完全处理。因此,在完成处理日志条目exit
之前就到达了该行。尝试查找发送日志记录的日志,但现在找不到它,因为该设备不再运行。journald
journald
unit
sleep 1
如果我是对的,我可能可以通过在我的声明之前解决这个问题exit 1
,但是有没有更好的方法来获得最终的日志属性?
systemd
我在 Ubuntu 16.04 上使用版本 229。
答案1
@mark-stosberg,这是一个已知问题:由于 /proc 与 SCM_CREDS 竞争,journald 无法将从退出的进程传入的消息归因于其 cgroup
您可以在那里找到解决方法:https://github.com/systemd/systemd/issues/2913#issuecomment-219702148
将进程名称设置为发送到日志系统或内核日志缓冲区的日志行的前缀。
并运行
journalctl _SYSTEMD_UNIT=unit + UNIT=unit + SYSLOG_IDENTIFIER=id
答案2
我研究了一下这个,看来是systemd 的已知问题,有一个拉取请求。
该修复涉及缓存服务的元数据,以便即使服务已退出,其元数据仍然可用于正确对最后几个日志进行分类。
它也被认为是CoreOS 中的开放错误,它使用 systemd。
该错误也在 systemd freedesktop.org 错误跟踪器上进行了跟踪,如下所示:
进一步测试发现,丢失日志归属的问题更加严重用户单位——我认为这是一个单独的问题。为了系统单位,竞争条件相对较小,并且sleep 1;
在服务脚本中的退出之前添加可以在打印的最后一个日志和退出之前添加足够的填充来解决问题。