我以前使用init.d/脚本来管理我编写的守护进程,这些守护进程多年来一直完美运行。现在我发现自己需要提供一个systemd/脚本,但我无法让它与我执行守护程序设置代码的方式一起工作。
当我设置一个守护进程时,我分叉两次以释放控制终端并避免成为会话领导者。
问题是我已经确认当你这样做时systemd/会失去跟踪并杀死守护进程。我还确认跳过第二个 fork 可以使其再次与systemd/一起工作。
我的基本(为了讨论的目的稍微简化)systemd/脚本是
[Unit]
Description=GM7 Service Daemon
[Service]
Type=forking
ExecStart=/usr/bin/g7ctrl
[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)
所以我想我的问题是:我是否需要改变过去十年在 C/C++ 中完成守护进程设置代码的方式,或者是否有选项让 systemd/ 来跟踪双分叉?
我还没有完全了解内部工作原理,如果 systemd 本身为它启动的每个守护进程生成进程,在这种情况下,我的双叉确实会过时
我承认我这样做的方式(双叉)部分是出于历史原因,但当时我对最佳实践进行了一些相当深入的阅读,这就是我后来想到的(大约十年前)
我目前正在开发一个 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 似乎没有检测到分叉,因为它在 …