英文:
Unable to `syscall.Kill()` a daemonized Go process
问题
我用Go语言编写了一个程序,使用syscall.Kill()
来终止一个进程。
但是,如果我使用fork()
和setsid()
将该进程变为守护进程,那么syscall.Kill()
将无法终止该进程。
如果我使用shell的kill
命令,则可以在两种情况下终止该进程。
我尝试了不同的信号:SIGINT
、SIGTERM
和SIGKILL
,但它们都无法终止守护进程。
英文:
I made program in Go that kills a process with syscall.Kill()
But if I daeminze that process with fork()
+ setsid()
then syscall.Kill()
does not kill that process.
If I use shell kill
then I'm able to kill that process in both cases.
I tried different signals: SIGINT
, SIGTERM
and SIGKILL
buthey do not kill the daemon.
答案1
得分: 6
使用系统调用来守护一个Go进程目前无法可靠地实现,这就是为什么你的类似守护进程的进程无法被杀死的原因:它被卡住了(尽管我必须承认,奇怪的是为什么它没有在发送SIGKILL
后死掉,因为这会让内核直接销毁进程,不会尝试发送信号)。
要正确地守护一个Go进程,建议使用一个包装进程(比如daemon
)或者在一个高级替代init
超级服务器(如systemd
或upstart
)下运行,或者使用一个独立的监控程序,如runit
、monit
等。在这种情况下,进程不需要像真正的Unix守护进程那样具备脑残的要求,可以像普通进程一样运行:不进行双重fork
+setsid
的技巧,不操纵PID文件管理,能够写入常规的I/O流等。
英文:
Daemonizing a Go process using syscalls is not currently possible to do reliably and that's why your sort-of-daemonized process was impossible to kill: it has been wedged (though I should admit it's weird why it did not die in response to sending SIGKILL
which makes the kernel just destroy the process, no signal delivery is attempted).
To properly daemonize a Go process one is advised to use a wrapper process (such as daemon
) or run it under an an advanced substitute for the init
superserver such as systemd
or upstart
or a standalone supervisor such as runit
, monit
and others—in which case the process has no braindead requirement to be a true Unix daemon and may behave like a normal process: does not perform double-fork
+setsid
trickery, does not mess with PID file management, is able to write to its regular I/O streams etc.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论