最近写一个小DEMO进行进程的关闭、构建、启动, 有段代码:
for {
ctx, cancel := context.WithCancel(context.Background())
cmd := exec.CommandContext(ctx, "go", "run", "main.go")
cmd.Stdout = os.Stdout
go func() {
<-rebuildNotifier //其他协程通知关闭程序
fmt.Println("执行关闭程序")
cancel()
}()
if err := cmd.Run(); err != nil {
log.Println(err)
}
fmt.Println("重新启动一个进程")
}
在执行的时候发现当执行cancel()
函数以后, cmd.Run
得到一个Killed
信号, 但是由exec.CommandContext
启动的进程居然没有被杀死, 依然坚挺的在输出内容.
如果将内容:
go func() {
<-rebuildNotifier //其他协程通知关闭程序
fmt.Println("执行关闭程序")
cancel()
}()
直接换成
cancel()
能够正常的得到结果, 但不是想要的(我可不想无限杀死cmd). 当 将代码:
cmd := exec.CommandContext(ctx, "go", "run", "main.go")
换成
// 构建main
cmd := exec.CommandContext(ctx, "./main")
代码能够正常执行了!
推断: 可能是
go run main.go
包含子进程, 当执行cancel
的时候是杀死了主进程, 子进程变成了孤儿进程. 具体需要代码测试结果.
资料:
golang的CommandContext取消不退出问题
golang使用execCommand调用的时候子进程如何杀掉处理方法