如何保证在程序退出时刷新 systemd 和 journald 之间的标准输出缓冲区?
How to guarantee the stdout buffer between systemd and journald is flushed when program quits?
演示问题的简化例子是
#include <stdio.h>
int main(void)
{
printf("foo\n");
fflush(stdout);
getchar();
return 0;
}
(尽管它不是特定于编程语言的 - 我发现问题的原始应用程序是在 Go 中)。
如果编译为运行以下单位:
[Unit]
Description=description
After=network.target
[Service]
ExecStart=/path/to/binary
[Install]
WantedBy=multi-user.target
然后 systemctl restart
journald
在大多数情况下不会得到 foo\n
输出,而 syslog
成功地将它写入 /var/log/syslog
。
这是服务的 journald
输出示例:
May 18 08:30:38 hostname systemd[1]: Stopped servicename
May 18 08:30:38 hostname systemd[1]: Started servicename
May 18 08:30:38 hostname systemd[1]: Stopped servicename
May 18 08:30:38 hostname systemd[1]: Started servicename
May 18 08:30:38 hostname servicename[7701]: foo
May 18 08:30:41 hostname systemd[1]: Stopped servicename
May 18 08:30:41 hostname systemd[1]: Started servicename
May 18 08:30:46 hostname systemd[1]: Stopped servicename
May 18 08:30:46 hostname systemd[1]: Started servicename
然后是/var/log/syslog
对应的部分:
May 18 08:30:38 hostname systemd[1]: Stopped servicename.
May 18 08:30:38 hostname systemd[1]: Started servicename.
May 18 08:30:38 hostname servicename[7682]: foo
May 18 08:30:38 hostname systemd[1]: Stopped servicename.
May 18 08:30:38 hostname systemd[1]: Started servicename.
May 18 08:30:38 hostname servicename[7701]: foo
May 18 08:30:41 hostname systemd[1]: Stopped servicename.
May 18 08:30:41 hostname systemd[1]: Started servicename.
May 18 08:30:41 hostname servicename[7720]: foo
May 18 08:30:46 hostname systemd[1]: Stopped servicename.
May 18 08:30:46 hostname systemd[1]: Started servicename.
May 18 08:30:46 hostname servicename[7739]: foo
有什么方法可以保证 journald 收到stdout
,如果有的话?
tldr,这是一个已知问题。
我在systemd-devel maillist and got a reply with a reference to the reported issue问了同样的问题。
演示问题的简化例子是
#include <stdio.h>
int main(void)
{
printf("foo\n");
fflush(stdout);
getchar();
return 0;
}
(尽管它不是特定于编程语言的 - 我发现问题的原始应用程序是在 Go 中)。
如果编译为运行以下单位:
[Unit]
Description=description
After=network.target
[Service]
ExecStart=/path/to/binary
[Install]
WantedBy=multi-user.target
然后 systemctl restart
journald
在大多数情况下不会得到 foo\n
输出,而 syslog
成功地将它写入 /var/log/syslog
。
这是服务的 journald
输出示例:
May 18 08:30:38 hostname systemd[1]: Stopped servicename
May 18 08:30:38 hostname systemd[1]: Started servicename
May 18 08:30:38 hostname systemd[1]: Stopped servicename
May 18 08:30:38 hostname systemd[1]: Started servicename
May 18 08:30:38 hostname servicename[7701]: foo
May 18 08:30:41 hostname systemd[1]: Stopped servicename
May 18 08:30:41 hostname systemd[1]: Started servicename
May 18 08:30:46 hostname systemd[1]: Stopped servicename
May 18 08:30:46 hostname systemd[1]: Started servicename
然后是/var/log/syslog
对应的部分:
May 18 08:30:38 hostname systemd[1]: Stopped servicename.
May 18 08:30:38 hostname systemd[1]: Started servicename.
May 18 08:30:38 hostname servicename[7682]: foo
May 18 08:30:38 hostname systemd[1]: Stopped servicename.
May 18 08:30:38 hostname systemd[1]: Started servicename.
May 18 08:30:38 hostname servicename[7701]: foo
May 18 08:30:41 hostname systemd[1]: Stopped servicename.
May 18 08:30:41 hostname systemd[1]: Started servicename.
May 18 08:30:41 hostname servicename[7720]: foo
May 18 08:30:46 hostname systemd[1]: Stopped servicename.
May 18 08:30:46 hostname systemd[1]: Started servicename.
May 18 08:30:46 hostname servicename[7739]: foo
有什么方法可以保证 journald 收到stdout
,如果有的话?
tldr,这是一个已知问题。
我在systemd-devel maillist and got a reply with a reference to the reported issue问了同样的问题。