Go\Linux - 子进程与父进程一起被杀死

问题描述 投票:0回答:1

在 Linux (ubuntu) 中使用 Go 语言。

服务(作为守护进程运行,可以通过

systemctl
找到,但不能通过
ps
找到)运行一个命令(参见代码),该命令运行一个可执行文件(不确定是否值得一提,但是 - 它们实际上是相同的可执行文件)代码)。

服务通过

github.com/kardianos/service
包进行管理。

作为子服务运行的代码的一部分 - 我需要停止父服务(

service.control("stop")
)。此时子进程也会失败,而不是继续流程的其余部分。

我尝试过:

  1. 设置会话 ID (

    Setsid=true
    )

  2. 设置群组ID (

    Setpgid-true
    )

  3. 调用

    Release()
     后在底层进程上调用 
    Start()

  4. 上述组合(如此处建议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
}
linux go
1个回答
0
投票

当进程领导进程退出时,子进程会收到 SIGHUP 信号。如果该信号既未被忽略,也未被处理,则默认情况下子级存在。

© www.soinside.com 2019 - 2024. All rights reserved.