英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论