在 Golang 中,如何使用 SIGTERM 而不是 SIGKILL 终止 os.exec.Cmd 进程?
In Golang, how to terminate an os.exec.Cmd process with a SIGTERM instead of a SIGKILL?
目前,我正在使用 Golang os.exec.Cmd.Process.Kill() 方法(在 Ubuntu 框上)终止进程。
这似乎是立即终止进程,而不是正常终止。我启动的一些进程也会写入文件,这会导致文件被截断。
我想使用 SIGTERM 而不是使用 Golang 的 SIGKILL 优雅地终止进程。
这是一个使用 cmd.Process.Kill() 启动然后终止的进程的简单示例,我想要 Golang 中使用 SIGTERM 而不是 SIGKILL 的 Kill() 方法的替代方法,谢谢!
import "os/exec"
cmd := exec.Command("nc", "example.com", "80")
if err := cmd.Start(); err != nil {
log.Print(err)
}
go func() {
cmd.Wait()
}()
// Kill the process - this seems to kill the process ungracefully
cmd.Process.Kill()
cmd.Process.Signal(syscall.SIGTERM)
你可以用Signal() API. The supported Syscalls都在这里
所以基本上你可能想使用
cmd.Process.Signal(syscall.SIGTERM)
另请根据文档注意。
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.
您可以使用:
cmd.Process.Signal(os.Interrupt)
测试示例:
package main
import (
"fmt"
"log"
"net"
"os"
"os/exec"
"sync"
"time"
)
func main() {
cmd := exec.Command("nc", "-l", "8080")
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
err := cmd.Wait()
if err != nil {
fmt.Println("cmd.Wait:", err)
}
fmt.Println("done")
wg.Done()
}()
fmt.Println("TCP Dial")
fmt.Println("Pid =", cmd.Process.Pid)
time.Sleep(200 * time.Millisecond)
// or comment this and use: nc 127.0.0.1 8080
w1, err := net.DialTimeout("tcp", "127.0.0.1:8080", 1*time.Second)
if err != nil {
log.Fatal("tcp DialTimeout:", err)
}
defer w1.Close()
fmt.Fprintln(w1, "Hi")
time.Sleep(1 * time.Second)
// cmd.Process.Kill()
cmd.Process.Signal(os.Interrupt)
wg.Wait()
}
输出:
TCP Dial
Pid = 21257
Hi
cmd.Wait: signal: interrupt
done
目前,我正在使用 Golang os.exec.Cmd.Process.Kill() 方法(在 Ubuntu 框上)终止进程。
这似乎是立即终止进程,而不是正常终止。我启动的一些进程也会写入文件,这会导致文件被截断。
我想使用 SIGTERM 而不是使用 Golang 的 SIGKILL 优雅地终止进程。
这是一个使用 cmd.Process.Kill() 启动然后终止的进程的简单示例,我想要 Golang 中使用 SIGTERM 而不是 SIGKILL 的 Kill() 方法的替代方法,谢谢!
import "os/exec"
cmd := exec.Command("nc", "example.com", "80")
if err := cmd.Start(); err != nil {
log.Print(err)
}
go func() {
cmd.Wait()
}()
// Kill the process - this seems to kill the process ungracefully
cmd.Process.Kill()
cmd.Process.Signal(syscall.SIGTERM)
你可以用Signal() API. The supported Syscalls都在这里
所以基本上你可能想使用
cmd.Process.Signal(syscall.SIGTERM)
另请根据文档注意。
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.
您可以使用:
cmd.Process.Signal(os.Interrupt)
测试示例:
package main
import (
"fmt"
"log"
"net"
"os"
"os/exec"
"sync"
"time"
)
func main() {
cmd := exec.Command("nc", "-l", "8080")
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
err := cmd.Wait()
if err != nil {
fmt.Println("cmd.Wait:", err)
}
fmt.Println("done")
wg.Done()
}()
fmt.Println("TCP Dial")
fmt.Println("Pid =", cmd.Process.Pid)
time.Sleep(200 * time.Millisecond)
// or comment this and use: nc 127.0.0.1 8080
w1, err := net.DialTimeout("tcp", "127.0.0.1:8080", 1*time.Second)
if err != nil {
log.Fatal("tcp DialTimeout:", err)
}
defer w1.Close()
fmt.Fprintln(w1, "Hi")
time.Sleep(1 * time.Second)
// cmd.Process.Kill()
cmd.Process.Signal(os.Interrupt)
wg.Wait()
}
输出:
TCP Dial
Pid = 21257
Hi
cmd.Wait: signal: interrupt
done