Linux
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); }
這是服務文件
/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
守護程序函式應該分叉程序並將其與終端分離,我還關閉文件描述符並將工作目錄更改為 /。
然而 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'.
有沒有人知道為什麼 systemd 沒有檢測到分叉?
我必須明確呼叫
fork()
我的程式碼嗎?
在這種情況下,我必須自己編寫 daemonize 函式,這並不難,但完全無用和多餘,因為為此目的已經存在 ac 函式。
不要那樣做。
完全沒有。任何一個,無論是通過庫函式還是滾動您自己的程式碼。適用於任何服務管理系統。自 1990 年代以來,這一直是一個錯誤的想法。
您的守護程序已經在服務上下文中執行,由服務管理器以這種方式呼叫。你的程序在這方面不應該做任何事情。完全停止以這種方式編寫程序。
並且不要使用
forking
就緒協議。您的程序是多執行緒的,如果您嘗試向其添加就緒協議,幾乎肯定無法正常執行forking
,因為正確制定協議意味著在所有初始化完成後分叉,包括啟動所有執行緒。幾乎沒有任何東西實際上forking
在野外使用就緒協議。使用其他協議。進一步閱讀
- https://unix.stackexchange.com/a/200365/5132
- https://unix.stackexchange.com/a/194653/5132
- https://unix.stackexchange.com/a/211126/5132
- https://unix.stackexchange.com/a/336067/5132
- https://unix.stackexchange.com/a/283739/5132
- 喬納森·德博因·波拉德 (2001)。“不要 fork() 為了‘把守護程序放到後台’。 ”。 設計 Unix 守護程序時要避免的錯誤。經常給出答案。
- 喬納森·德博因·波拉德 (2015)。你真的不需要守護程序。真的。. 系統化的恐怖屋。
- 喬納森·德博因·波拉德 (2015)。Unix 守護程序的就緒協議問題。經常給出答案。