Systemd 超时,因为它没有检测到守护进程分叉

Ark*_*aik 3 linux fork systemd timeout daemon

我目前正在开发一个 systemd 守护进程。我面临的问题是守护进程在蜜蜂启动后 1 分 30 秒被杀死,因为没有检测到分叉。

我正在使用该int daemon(int nochdir, int noclose)函数来守护进程。

int main()
{
    openlog("shutdownd", LOG_PID, LOG_DAEMON);

    if(daemon(0, 0) != 0)
    {
        syslog(LOG_ERR, "Error daemonizing process : %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    syslog(LOG_NOTICE, "Daemon started !\n");

    pthread_create(&threads[0], NULL, &alimThread, NULL);
    pthread_create(&threads[1], NULL, &extinctThread, NULL);
    pthread_create(&threads[2], NULL, &blinkThread, NULL);

    while(1)
    {
    }

    syslog(LOG_NOTICE, "Daemon stopped !\n");
    exit(EXIT_SUCCESS);
}
Run Code Online (Sandbox Code Playgroud)

这是服务文件 /etc/systemd/system/shutdownd.service

[Unit]
Description=Shutdown Daemon
After=syslog.target

[Service]
Type=forking
PIDFile=/var/run/shutdownd.pid
ExecStartPre=/bin/rm -f /var/run/shutdownd.pid
ExecStartPre=/usr/bin/shutdownd-exportGpio.sh
ExecStart=/usr/bin/shutdownd
Restart=on-abort

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

守护程序函数应该派生进程并将其与终端分离,我还关闭文件描述符并将工作目录更改为 /。

然而,systemd 似乎没有检测到分叉,因为它在 1 分 30 秒后杀死了我正在运行的守护进程。

Sep  8 13:52:50 raspberrypi systemd[1]: shutdownd.service: PID file /var/run/shutdownd.pid not readable (yet?) after start: No such file or directory
Sep  8 13:52:50 raspberrypi shutdownd[293]: Daemon started !
Sep  8 13:52:50 raspberrypi shutdownd[293]: [Extinct] Value changed to 0
Sep  8 13:52:50 raspberrypi shutdownd[293]: OFF
Sep  8 13:52:50 raspberrypi shutdownd[293]: [Alim] Value changed to 0
Sep  8 13:52:50 raspberrypi shutdownd[293]: OFF
Sep  8 13:53:46 raspberrypi shutdownd[293]: [Alim] Value changed to 1
Sep  8 13:53:46 raspberrypi shutdownd[293]: Toogle : ON
Sep  8 13:53:48 raspberrypi shutdownd[293]: Toogle : OFF
[...]
Sep  8 13:54:16 raspberrypi shutdownd[293]: [Extinct] Value changed to 1
Sep  8 13:54:16 raspberrypi shutdownd[293]: ON
Sep  8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Start operation timed out. Terminating.
Sep  8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Unit entered failed state.
Sep  8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Failed with result 'timeout'.
Run Code Online (Sandbox Code Playgroud)

有没有人知道为什么 systemd 没有检测到分叉?

我是否必须显式调用fork()我的代码?
在这种情况下,我将不得不自己编写 daemonize 函数,这并不难,但完全没用且多余,因为为此目的已经存在 ac 函数。

Jde*_*eBP 9

不要那样做。

在所有。任何一个,通过库函数或滚动你自己的代码。适用于任何服务管理系统。自 1990 年代以来,这一直是一个错误的想法。

您的守护进程已经在服务上下文中运行,由服务管理器以这种方式调用。你的程序在这方面应该做任何事情。完全停止以这种方式编写程序。

并且不要使用forking就绪协议。您的程序是多线程的,如果您尝试向其中添加forking就绪协议,几乎肯定不会正常运行,因为正确制定协议意味着在完成所有初始化(包括启动所有线程)后进行分叉。几乎没有任何东西在实际中使用forking就绪协议。使用其他协议。

进一步阅读

  • `Type=forking` 用于告诉 systemd 该守护进程是一个老派的分叉守护进程。如果调用了`daemon()`,则应该*使用`Type=forking`;如果服务可执行文件不分叉,则不应*使用它。但是我完全同意 JdeBP 的观点,您应该将它留给 systemd 来守护进程,并且仅将 `Type=forking` 用于遗留守护程序。回到你原来的问题:我认为 systemd *是* 检测到程序分叉并且父退出,但我怀疑 systemd 仍在等待 PIDFile 出现。Systemd 不写这个文件,守护进程应该写它。 (2认同)