登录
首页 >  Golang >  Go问答

终止 golang 中执行 exec.command 的子进程

来源:stackoverflow

时间:2024-02-12 20:54:26 362浏览 收藏

小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《终止 golang 中执行 exec.command 的子进程》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!

问题内容

这似乎是一个类似的问题在互联网上流传,但事实并非如此,因为我没有找到任何类似的问题,所以在这里提问。

问题是,我有一个名为 abc.go 的 go 程序,其中包含两个用于运行和停止 somescript.sh 脚本的函数。 run() 和 stop() 在 api 命中时被调用。我正在使用命令 sudo go run abc.go somefolder/somescript.sh 运行此 abc.go 文件,同时传递 somescript.sh 路径作为参数。在stop()中,我正在保存进程组id,然后杀死整个进程组。

但是当我调用 run 然后 stop 函数时,它会给我这个输出

pid=5844 duration=13.667µs err=exec: already started

并且实际上并没有停止正在运行的 docker 容器(我正在使用 docker 容器 ls -a 进行检查)。

somescript.sh 文件是:

#!/bin/bash
docker container run --rm --name somecontainername nginx

abc.go 文件是:

func run(){
    somevar= true
    execcmd = exec.command("/bin/sh", "-c", commandfromterminal)
    output, err = execcmd.combinedoutput()
    fmt.println("output()=", bp.output())
    somevar= false
}

func stop(){
    execcmd.sysprocattr = &syscall.sysprocattr{setpgid: true}
    start := time.now()
    syscall.kill(-execcmd.process.pid, syscall.sigkill)
    err := execcmd.run()
    fmt.printf("pid=%d duration=%s err=%s\n", execcmd.process.pid, time.since(start), 
    err)
}

根据我的理解,似乎用 somescript.sh 编写的 docker 命令并没有将 docker 容器作为 /bin/bash 的子子/孙子运行,而是将其作为一个单独的进程运行,其中的代码我的 stop() 无法实际停止它

下面是根据我的理解的流程图,我认为在调用 abc.go 时,它在内部调用 /bin/bash,然后运行 ​​sudo 作为其子项,进一步 sudo 有一个 subchildsomescript.sh。最后是 docker,它不作为上述层次结构的任何子/子子运行,而是作为不同的进程运行。

我的问题最后是,如何在调用 stop() 时停止此 docker 容器。或者如何使这个 docker 容器作为层次结构的子子运行,以便我可以使用上面使用的 process-groupid 方法杀死它。

ps:我也尝试过

err := execCMD.Process.Kill()
    if err != nil {
        panic(err.Error())
    }
    execCMD.Process.Release()

但这也没有帮助。


正确答案


docker 只是 docker 守护进程的客户端。 docker run 只需向守护进程发送一些 HTTP 请求,守护进程就会设置容器并执行它。

所以 docker run 是你的 Go 程序的孙子,但 nginx 进程是 Docker 守护进程的后代,与你的 Go 程序完全无关。请注意,至少原则上,docker 守护进程甚至可以位于不同的机器上。

话虽如此,

  1. 在进程启动后分配 SysProcAttr 无效。
  2. 您在 Stop 中调用 Run(非常可疑),并且您无法运行已启动的进程,即使在其终止后也是如此。
  3. 发送 SIGKILL 使 docker run 没有机会终止容器。修复其他错误后,docker 守护进程可能会由于 --rm 标志而负责清理(我完全忘记了它是如何工作的)。如果没有,则发送 SIGTERM。

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>