Linux|如何避免 Go 命令行执行产生“孤儿”进程?( 三 )


// 其他内容省略掉了const( .... PR_SET_PDEATHSIG = 0x1 ....)const( ..... SYS_PRCTL = 157 .....) 其中 PR_SET_PDEATHSIG 操作的值为 1 , SYS_PRCTL 的值为 157 , 那么将 child.go 修改成如下内容:
package mainimport ( \"fmt\" \"os\" \"syscall\" \"time\")func main() { _ _ errno := syscall.RawSyscall(uintptr(syscall.SYS_PRCTL) uintptr(syscall.PR_SET_PDEATHSIG) uintptr(syscall.SIGKILL) 0) if errno != 0 { os.Exit(int(errno))for { time.Sleep(200 * time.Millisecond) fmt.Println(time.Now())再次编译并执行:
go build -o child child.go./mainps -efUID PID PPID C STIME TTY TIME CMDroot 1 0 0 06:05 pts/0 00:00:00 /bin/bashroot 12208 1 0 12:46 pts/0 00:00:00 ./mainroot 12214 12208 0 12:46 pts/0 00:00:00 ./child 将 main 进程结束掉:
kill -9 12208ps -efUID PID PPID C STIME TTY TIME CMDroot 1 0 0 06:05 pts/0 00:00:00 /bin/bash child 进程已经退出了 , 也达成了最终效果 。
四 总结 当我们使用 Go 程序执行其他程序的时候 , 如果其他程序也开启了其他进程 , 那么在 kill 的时候可能会把这些进程变成孤儿进程 , 一直执行并滞留在内存中 。 当然 , 如果我们程序非法退出 , 或者被 kill 调用 , 也会导致我们执行的进程变成孤儿进程 , 那么为了解决这个问题 , 从两个思路来解决:
给要执行的程序创建新的进程组 , 并调用 syscall.Kill , 传递负值 pid 来关闭这个进程组中所有的进程(比较完美的解决方法) 。如果要调用的程序也是我们自己编写的 , 那么可以使用 PR_SET_PDEATHSIG 来感知父进程退出 , 那么这种方式需要调用 Linxu 的 prctrl , 可以使用 CGO 的方式 , 也可以使用 syscall.RawSyscall 的方式 。但不管使用哪种方式 , 都只是提供了一种思路 , 在我们编写服务端服务程序的时候 , 需要特殊关注 , 防止孤儿进程消耗服务器资源 。
作者 | 昕希
【Linux|如何避免 Go 命令行执行产生“孤儿”进程?】本文为阿里云原创内容 , 未经允许不得转载 。