问题描述
目前,我正在使用 Golang os.exec.Cmd.Process.Kill() 方法(在 Ubuntu 机器上)终止进程。
这似乎是立即终止进程,而不是优雅地终止。我启动的一些进程也会写入文件,这会导致文件被截断。
我想使用 Golang 使用 SIGTERM 而不是 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()
解决方法
您可以使用 Signal() API。支持的 Syscalls 在这里。
所以基本上你可能想要使用
cmd.Process.Signal(syscall.SIGTERM)
另外请注意按照文档。
保证出现在 os 包中的唯一信号值 所有系统都是 os.Interrupt(向进程发送中断)和 os.Kill(强制进程退出)。在 Windows 上,发送 os.Interrupt 没有实现带有 os.Process.Signal 的进程;它会回来 错误而不是发送信号。
,cmd.Process.Signal(syscall.SIGTERM)
,
您可以使用:
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