最近写一个小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调用的时候子进程如何杀掉处理方法