在 Linux (ubuntu) 中使用 Go 语言。
服务(作为守护进程运行,可以通过
systemctl
找到,但不能通过 ps
找到)运行一个命令(参见代码),该命令运行一个可执行文件(不确定是否值得一提,但是 - 它们实际上是相同的可执行文件)代码)。
服务通过
github.com/kardianos/service
包进行管理。
作为子服务运行的代码的一部分 - 我需要停止父服务(
service.control("stop")
)。此时子进程也会失败,而不是继续流程的其余部分。
我尝试过:
设置会话 ID (
Setsid=true
)
设置群组ID (
Setpgid-true
)
调用
Release()
后在底层进程上调用
Start()
上述组合(如此处建议https://groups.google.com/g/golang-nuts/c/Jx-ZsdQIMJA)
不确定我还有什么其他选择,并且希望得到您的建议。
初始化进程的函数代码(注意:这是我尝试过的内容的混合。我也分别尝试过它们等):
func ExecuteCommandAsync(command, args string, detach bool) error {
logger.Notify("Running cli command:", command, args)
cmd := exec.Command(command, args)
if detach {
logger.Notify("Detaching from parent process")
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true, // new session id prevents sigkill to parent kill the child
//Setpgid: true, // new group id prevents sigkill to parent kill the child
}
}
err := cmd.Start()
if err != nil {
logger.Error("Failed running cli command:", command, err)
return err
}
if detach {
logger.Notify("Detached from parent process - releasing child process")
err = cmd.Process.Release()
if err != nil {
return err
}
} else {
go func() {
logger.Notify("Waiting for cli command to finish")
waitErr := cmd.Wait()
if waitErr != nil {
logger.Error("Error waiting for cli command to finish:", waitErr)
} else {
logger.Notify("Command finished successfully")
}
}()
}
return nil
}
停止服务的函数代码:
func systemStopService(s service.Service) error {
if s == nil {
return errors.New("stopService - service is nil")
}
logger.Notify(s.String() + " Stopping service")
err := service.Control(s, "stop")
if err == nil {
logger.Notify(s.String() + " Service stopped")
} else if strings.Contains(err.Error(), "service does not exist") ||
strings.Contains(err.Error(), "service has not been started") {
logger.Notify(s.String() + err.Error())
err = nil // not an error
} else {
logger.Error(s.String()+" Failed to stop service", err)
}
return err
}
当进程领导进程退出时,子进程会收到 SIGHUP 信号。如果该信号既未被忽略,也未被处理,则默认情况下子级存在。