在 Golang 中终止使用 os/exec 启动的进程

新手上路,请多包涵

有没有办法终止在 Golang 中以 os.exec 启动的进程?例如(来自 http://golang.org/pkg/os/exec/#example_Cmd_Start ),

 cmd := exec.Command("sleep", "5")
err := cmd.Start()
if err != nil {
    log.Fatal(err)
}
log.Printf("Waiting for command to finish...")
err = cmd.Wait()
log.Printf("Command finished with error: %v", err)

有没有办法提前终止该进程,也许在 3 秒后?

提前致谢

原文由 Tech163 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

运行并终止 exec.Process

 // Start a process:
cmd := exec.Command("sleep", "5")
if err := cmd.Start(); err != nil {
    log.Fatal(err)
}

// Kill it:
if err := cmd.Process.Kill(); err != nil {
    log.Fatal("failed to kill process: ", err)
}

在超时后运行并终止 exec.Process

 ctx, cancel := context.WithTimeout(context.Background(), 3 * time.Second)
defer cancel()

if err := exec.CommandContext(ctx, "sleep", "5").Run(); err != nil {
    // This will fail after 3 seconds. The 5 second sleep
    // will be interrupted.
}

Go 文档 中查看此示例


遗产

在 Go 1.7 之前,我们没有 context 包,这个答案是不同的。

使用通道和 goroutine 在超时后运行并终止 exec.Process

 // Start a process:
cmd := exec.Command("sleep", "5")
if err := cmd.Start(); err != nil {
    log.Fatal(err)
}

// Wait for the process to finish or kill it after a timeout (whichever happens first):
done := make(chan error, 1)
go func() {
    done <- cmd.Wait()
}()
select {
case <-time.After(3 * time.Second):
    if err := cmd.Process.Kill(); err != nil {
        log.Fatal("failed to kill process: ", err)
    }
    log.Println("process killed as timeout reached")
case err := <-done:
    if err != nil {
        log.Fatalf("process finished with error = %v", err)
    }
    log.Print("process finished successfully")
}

进程结束并通过 done 接收到它的错误(如果有),或者 3 秒过去了并且程序在完成之前被终止。

原文由 Zippo 发布,翻译遵循 CC BY-SA 4.0 许可协议

其他关于调用 Kill() 的答案是正确的,但是关于在超时后终止进程的部分现在已经过时了。

现在可以使用 context 包和 exec.CommandContext 来完成(示例改编自文档中的示例):

 func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
    defer cancel()

    if err := exec.CommandContext(ctx, "sleep", "5").Run(); err != nil {
        // This will fail after 100 milliseconds. The 5 second sleep
        // will be interrupted.
    }
}

从文档:

如果上下文在命令自行完成之前完成,则提供的上下文用于终止进程(通过调用 os.Process.Kill)。

Run() 完成后,您可以检查 ctx.Err() 。如果达到超时,则返回的错误类型将为 DeadLineExceeded 。如果它是 nil ,请检查 errRun() 返回,以查看命令是否完成且没有错误。

原文由 David Castillo 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题