杀死子进程-exec.Command

你如何杀死子进程?

我有一个长时间运行的应用程序,使用“exec.Command”启动一个新进程:

// ...I am a long running application in the background

// Now I am starting a child process, that should be killed togeter with the parent application.
cmd := exec.Command("sh", "-c", execThis)

// create a new process group
// cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}

现在,如果我杀死<pid of long running application in the background>它不会杀死子进程 - 你知道怎么做吗?

回答

这里有很多事情要分开。

首先,操作系统本身做了什么。然后,一旦我们知道操作系统是什么以及它做了什么,程序就会做什么。

操作系统所做的显然是依赖于操作系统的。POSIX 风格的操作系统有两种kill:plainkill和 process-group-based kill,或者killpg. 这个函数的 killpg 变种是唯一一个向整个进程发送信号的函数普通kill只是向单个进程发送信号。

当程序从控制终端运行时,键盘信号(^C、^Z 等)被发送到该控制终端的前台进程组(有关这些的合理描述,请参阅链接页面并注意 BSD/macOS有 ^TSIGINFO以及)。但是,如果信号是从其他程序发送的,而不是从控制终端发送的,则由该程序决定是否调用killpgkill以及发送什么信号。

有些信号无法捕捉。SIGKILL 和 SIGSTOP 就是这种情况。这些信号不应发送无可奈何; 他们应该保留到最后的手段。相反,希望另一个程序停止的程序通常应该发送 SIGINT、SIGTERM、SIGHUP 或(很少)SIGQUIT 之一。Go 倾向于将 SIGQUIT 绑定到调试(因为 POSIX 系统上的运行时使 ^ 转储各种 goroutine 的堆栈),因此这不是一个好的选择。但是,这不取决于您在这里编写的Go程序,它只能尝试捕获信号。发送内容的选择取决于发件人。

捕捉信号的“Go 方式”是使用 goroutine 和 channel。该signal.Notify函数将操作系统级别的信号转换为通道上的事件。您不(也不可能)知道信号是否通过或到达您的进程(尽管如果它来自控制终端交互,POSIX-y 内核通过等效的 发送它)。如果您想自己传播该信号,只需使用通知事件来调用进行操作系统级调用的代码。当使用的包,使用:请注意,这个调用POSIX ,而不是它的killkillpgkillpgkillos/execcmd.Process.Signalkillkillpg,但你不会想使用killpg 在这里,因为我们首先假设一个非进程组信号(基于 pgroup 的信号可能不需要传播)。

没有完全可移植的方式将信号发送到 POSIX 进程组(这并不奇怪,因为这不能移植到非 POSIX 系统)。可悲的是,在 Go 中似乎也没有直接的 Unix 或 POSIX 特定的方法来做到这一点。

在非 POSIX 系统上,一切都大不相同。见前方附近的讨论的os/signal包。


以上是杀死子进程-exec.Command的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>