我在基于 yocto 的 Linux 发行版上工作。我不是专家systemd
,也不是systemd-journald
.
我的 C 程序my_c_program
在启动时由脚本启动my_script.sh
。下面是文件my_script.sh
:
my_c_program &
echo $! > /dev/shm/my_c_program.pid
以前的脚本由服务启动。服务的单元文件称为start_c_program.service
. 下面是单元服务:
[Unit]
Description=Start my_c_program
Requires=...
After=...
Before=...
[Service]
Type=forking
ExecStart=/usr/bin/my_script.sh
PIDFile=/dev/shm/my_c_program.pid
[Install]
WantedBy=multi-user.target
使用此配置,所有指令都printf("message")
将my_c_program
字符串添加"message"
到systemd-journald
. 我知道如果我修改my_script.sh
为:
my_c_program > /dev/null &
echo $! > /dev/shm/my_c_program.pid
on 上的消息journald
被抑制,但问题是:
为什么我的 C 程序的所有输出都指向 stdout 被发送到journald
?
谢谢
我在想,要向我发送消息,journald
我必须使用 C 指令syslog()
,例如通过如下代码:
#include<syslog.h>
int main(int argc, char** argv) {
syslog(LOG_INFO, "Start logging");
}
Systemd 将已执行进程的标准输出连接到它的日志。标准输出也被所有子进程继承,这就是为什么您的 C 程序将内容打印到日志中的原因。您可以使用StandardOutput=参数将程序的标准输出重定向到其他地方。
这是 systemd 的一个设计特点,实际上在现代软件中更为常见。
现代设计正在从软件自己决定将日志发送到哪里转向让运行器(在本例中为 systemd)决定要做什么。软件本身只是写入 stdout 和 stderr。在 Docker 或 Kubernetes 中运行的容器化软件具有非常相似的模式。
许多程序不知道如何写入 syslog,这比只写入 stdout/stderr 要复杂一些。Syslog 从未完全普遍存在,并且此类程序以前可能会将其 stdout/stderr 重定向到 var log 中的日志文件。
当 systemd 启动您的程序时,通过在运行您的程序之前替换进程的文件句柄,将 stdout 和 stderr 重定向到 journald。