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

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

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()方法的替代方法,谢谢!

import "os/exec"

cmd := exec.Command("nc", "example.com", "80")
if err := cmd.Start(); err != nil {
   log.Print(err)
}
go func() {
  cmd.Wait()
}()
// 终止进程 - 这似乎是非优雅地终止进程
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!

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()

答案1

得分: 7

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

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

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

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

cmd.Process.Signal(syscall.SIGTERM)

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

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

答案3

得分: 1

你可以使用以下代码:

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
英文:

You may use:

cmd.Process.Signal(os.Interrupt)

Tested example:

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()
}

Output:

TCP Dial
Pid = 21257
Hi
cmd.Wait: signal: interrupt
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:

确定