Golang如何阻止signal传递给os/exec执行的命令
场景
项目中使用signal
包捕获了关闭程序相关的信号(SIGHUP,SIGINT,SIGKILL),在程序执行时,使用Ctrl+C
结束进程,捕获这些信号后需要进行一些其它的处理,但是程序中使用os/exec
包执行了额外的命令,本意是在控制台中执行Ctrl+C
结束进程的时候能够将os/exec
执行的命令执行完毕后进程再退出,实现平滑的退出。
但是问题是触发Ctrl+C
的时候,虽然主程序捕获到了信号也能够对程序的行为进行控制,但是同时os/exec
执行的命令也会受到这个信号退出,无法实现完全的平滑退出。
信号处理相关代码
signalChan := make(chan os.Signal, 1)
signal.Notify(
signalChan,
syscall.SIGHUP,
syscall.SIGUSR2,
syscall.SIGINT,
syscall.SIGKILL,
)
go func() {
for {
sig := <-signalChan
switch sig {
case syscall.SIGUSR2, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL:
log.Debug("Received exit signal, waiting for exit...")
for _, channel := range runtime.Channels {
channel.StopChan <- struct{}{}
}
runtime.StopScheduler <- struct{}{}
runtime.StopHTTPServer <- struct{}{}
}
}
}()
使用os/exec
执行命令部分
cmd := exec.Command(params[0], params[1:]...)
问题
谷歌、百度许久没有找到相关的解决方案,查阅了官方文档关于os/signal
的描述,其中有这么一段
Subprocesses started by os.Exec, or by the os/exec package, will inherit the modified signal mask.
有什么方法能够只让主进程收到信号,而阻止os/exec
启动的子进程命令收到信号吗?或者是将收到的信号修改为其它信号,避免子进程退出?
项目地址为https://github.com/mylxsw/task-runner,如果可能,你可以看看我的源码,或许更加方便定位问题吧。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
半年前的提问,我现在回答会不会太晚。
刚好碰到这个问题, *nix环境中, 由exec.command开启的子进程的进程组ID默认为为父进程ID,需设置子进程的进程组ID为子进程自身ID
另外,
SIGKILL
相当于kill -9,不能被捕获重新翻了我的旧代码,然后再拿出来测试了可以!