在Golang中,如何使用SIGTERM而不是SIGKILL终止os.exec.Cmd进程?

huangapple go评论127阅读模式
英文:

In Golang, how to terminate an os.exec.Cmd process with a SIGTERM instead of a SIGKILL?

问题

目前,我正在使用Golang的**os.exec.Cmd.Process.Kill()**方法终止一个进程(在Ubuntu上)。

这似乎会立即终止进程,而不是优雅地终止。我启动的一些进程还会写入文件,这会导致文件被截断。

我想使用Golang以SIGTERM而不是SIGKILL优雅地终止进程。

以下是一个简单的示例,启动并使用cmd.Process.Kill()终止进程,我希望有一个在Golang中使用SIGTERM而不是SIGKILL的Kill()方法的替代方法,谢谢!

  1. import "os/exec"
  2. cmd := exec.Command("nc", "example.com", "80")
  3. if err := cmd.Start(); err != nil {
  4. log.Print(err)
  5. }
  6. go func() {
  7. cmd.Wait()
  8. }()
  9. // 终止进程 - 这似乎是非优雅地终止进程
  10. cmd.Process.Kill()
英文:

Currently, I am terminating a process using the Golang os.exec.Cmd.Process.Kill() method (on an Ubuntu box).

This seems to terminate the process immediately instead of gracefully. Some of the processes that I am launching also write to files, and it causes the files to become truncated.

I want to terminate the process gracefully with a SIGTERM instead of a SIGKILL using Golang.

Here is a simple example of a process that is started and then terminated using cmd.Process.Kill(), I would like an alternative in Golang to the Kill() method which uses SIGTERM instead of SIGKILL, thanks!

  1. import "os/exec"
  2. cmd := exec.Command("nc", "example.com", "80")
  3. if err := cmd.Start(); err != nil {
  4. log.Print(err)
  5. }
  6. go func() {
  7. cmd.Wait()
  8. }()
  9. // Kill the process - this seems to kill the process ungracefully
  10. cmd.Process.Kill()

答案1

得分: 7

你可以使用Signal() API。支持的Syscalls在这里。

所以基本上你可能想要使用:

  1. cmd.Process.Signal(syscall.SIGTERM)

另请注意,根据文档。

> 在所有系统上,os包中保证存在的唯一信号值是os.Interrupt(发送中断信号给进程)和os.Kill(强制进程退出)。在Windows上,使用os.Process.Signal向进程发送os.Interrupt信号没有实现;它会返回一个错误而不是发送信号。

英文:

You can use Signal() API. The supported Syscalls are here.

So basically you might want to use

  1. cmd.Process.Signal(syscall.SIGTERM)

Also please note as per documentation.

> The only signal values guaranteed to be present in the os package on
> all systems are os.Interrupt (send the process an interrupt) and
> os.Kill (force the process to exit). On Windows, sending os.Interrupt
> to a process with os.Process.Signal is not implemented; it will return
> an error instead of sending a signal.

答案2

得分: 2

  1. cmd.Process.Signal(syscall.SIGTERM)

这行代码是用于发送终止信号给进程的。

英文:
  1. cmd.Process.Signal(syscall.SIGTERM)

答案3

得分: 1

你可以使用以下代码:

  1. cmd.Process.Signal(os.Interrupt)

测试示例:

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "os"
  7. "os/exec"
  8. "sync"
  9. "time"
  10. )
  11. func main() {
  12. cmd := exec.Command("nc", "-l", "8080")
  13. cmd.Stderr = os.Stderr
  14. cmd.Stdout = os.Stdout
  15. cmd.Stdin = os.Stdin
  16. err := cmd.Start()
  17. if err != nil {
  18. log.Fatal(err)
  19. }
  20. var wg sync.WaitGroup
  21. wg.Add(1)
  22. go func() {
  23. err := cmd.Wait()
  24. if err != nil {
  25. fmt.Println("cmd.Wait:", err)
  26. }
  27. fmt.Println("done")
  28. wg.Done()
  29. }()
  30. fmt.Println("TCP Dial")
  31. fmt.Println("Pid =", cmd.Process.Pid)
  32. time.Sleep(200 * time.Millisecond)
  33. // or comment this and use: nc 127.0.0.1 8080
  34. w1, err := net.DialTimeout("tcp", "127.0.0.1:8080", 1*time.Second)
  35. if err != nil {
  36. log.Fatal("tcp DialTimeout:", err)
  37. }
  38. defer w1.Close()
  39. fmt.Fprintln(w1, "Hi")
  40. time.Sleep(1 * time.Second)
  41. // cmd.Process.Kill()
  42. cmd.Process.Signal(os.Interrupt)
  43. wg.Wait()
  44. }

输出:

  1. TCP Dial
  2. Pid = 21257
  3. Hi
  4. cmd.Wait: signal: interrupt
  5. done
英文:

You may use:

  1. cmd.Process.Signal(os.Interrupt)

Tested example:

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "os"
  7. "os/exec"
  8. "sync"
  9. "time"
  10. )
  11. func main() {
  12. cmd := exec.Command("nc", "-l", "8080")
  13. cmd.Stderr = os.Stderr
  14. cmd.Stdout = os.Stdout
  15. cmd.Stdin = os.Stdin
  16. err := cmd.Start()
  17. if err != nil {
  18. log.Fatal(err)
  19. }
  20. var wg sync.WaitGroup
  21. wg.Add(1)
  22. go func() {
  23. err := cmd.Wait()
  24. if err != nil {
  25. fmt.Println("cmd.Wait:", err)
  26. }
  27. fmt.Println("done")
  28. wg.Done()
  29. }()
  30. fmt.Println("TCP Dial")
  31. fmt.Println("Pid =", cmd.Process.Pid)
  32. time.Sleep(200 * time.Millisecond)
  33. // or comment this and use: nc 127.0.0.1 8080
  34. w1, err := net.DialTimeout("tcp", "127.0.0.1:8080", 1*time.Second)
  35. if err != nil {
  36. log.Fatal("tcp DialTimeout:", err)
  37. }
  38. defer w1.Close()
  39. fmt.Fprintln(w1, "Hi")
  40. time.Sleep(1 * time.Second)
  41. // cmd.Process.Kill()
  42. cmd.Process.Signal(os.Interrupt)
  43. wg.Wait()
  44. }

Output:

  1. TCP Dial
  2. Pid = 21257
  3. Hi
  4. cmd.Wait: signal: interrupt
  5. done

huangapple
  • 本文由 发表于 2021年7月23日 12:57:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/68494240.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定