超值的郑州网站建设,分享类wordpress主题,专门做名片的网站,抖音运营推广策划方案平常我们启动一个后台进程#xff0c;会通过nouhp 的方式启动#xff0c;这样可以在退出终端会话的时候#xff0c;进程仍然可以继续在后台执行(进程的父进程id会从原来的bash进程变成1) 在go程序中#xff0c;通过nouhp 的方式启动子进程#xff0c;预期是即使…平常我们启动一个后台进程会通过nouhp 的方式启动这样可以在退出终端会话的时候进程仍然可以继续在后台执行(进程的父进程id会从原来的bash进程变成1) 在go程序中通过nouhp 的方式启动子进程预期是即使父进程挂掉子进程也能继续执行 但是测试过程中发现当父进程被kill子进程也会自动退出
首先需要了解下什么是SIGHUP和SIGTERM
1.SIGHUPHangup信号通常是由终端或控制台断开时产生的信号它的作用是通知进程重新读取其配置文件或者让进程重新初始化以便于适应新的环境。在进程收到该信号时一般会在日志中记录相关信息然后进行优雅的退出或重新初始化。
2.SIGTERMTerminate信号是进程终止信号它通常是由kill命令发送给进程的。它的作用是请求进程正常地退出进程在接收到该信号后可以在清理后退出。如果进程没有处理SIGTERM信号则可以使用kill -9命令强制杀死进程。正常情况下一个程序如果没有进行特别处理那么收到SIGHUP、SIGTERM信号都会退出
通常我们在一个终端会话中启动一个进程如果只是通过后台启动那么当会话关闭的时候进程也会自动退出 这是因为会话关闭的时候会向子进程发送SIGHUP信号导致子进程也跟着退出 而nohup的作用就是忽略NOHUP信号避免进程退出
go程序中可以用signal.Notify监听SIGHUP信号修改默认行为示例代码
package mainimport (fmtosos/signalsyscall
)func main() {// 创建一个channel用于接收信号signals : make(chan os.Signal, 1)// 注册信号signal.Notify(signals, syscall.SIGTERM, syscall.SIGHUP)// 在goroutine中等待信号go func() {for {select {case sig : -signals:switch sig {case syscall.SIGTERM:fmt.Println(Received SIGTERM, shutting down gracefully...)// 做一些清理工作os.Exit(0)case syscall.SIGHUP:fmt.Println(Received SIGHUP, reloading configuration...)// 重新加载配置}}}}()// 主进程继续执行其他任务fmt.Println(Server started...)select {}
}通过在子进程中用signal.Notify监听SIGHUP、SIGTERM信号并打印日志来进行测试(kill -1发送SIGHUP信号kill发送SIGTERM信号) 查看日志发现父进程被kill子进程会收到SIGTERM信号 而nohup只是忽略SIGHUP信号所以使用nohup启动自然就不能防止子进程退出了
解决方案是启动子进程时修改子进程进程组id这样子进程就不会收到SIGTERM信号了 Go示例代码
package mainimport (fmtos/execstringssyscall
)func main() {//这里child是上面子进程编译成的二进制程序cmd : exec.Command(/bin/bash, -c, ./child)//SysProcAttr 字段被设置为 Setpgid 为 true这将使子进程的进程组 ID 与其父进程不同。Pdeathsig 被设置为空信号这意味着子进程在父进程退出时不会收到任何信号cmd.SysProcAttr syscall.SysProcAttr{Setpgid: true,Pdeathsig: syscall.Signal(0),}output, err : cmd.CombinedOutput()rs : strings.TrimSpace(string(output))if err ! nil {fmt.Println(Command execution failed:, err, rs:, rs)os.Exit(1)}fmt.Println(rs:, rs)
}ps -eo pid,ppid,pgrp,session,comm 可以通过这个命令来查看进程进程组id
还有一种情况要注意即使不用Setpgid使用kill -9的方式杀父进程子进程也是不会退出的 针对一些希望父进程结束的时候子进程也被跟着退出的场景要么谨慎使用kill -9要么自己做好进程退出的机制处理
参考资料 https://blog.csdn.net/qq_34021712/article/details/115587702 https://cloud.tencent.com/developer/article/1497217 https://www.jianshu.com/p/e147d856074c%20