在 Go 中运行命令并将其与进程分离
问题:
你需要在 Go 中执行一个长时间运行的进程,并确保:
尝试的解决方案:
您尝试使用 cmd.Start() 和 cmd.Process.Release(),但它们并不能阻止程序退出时进程变成僵尸进程。你还希望进程尽可能独立,有自己的父PID、组PID等
解决方案:
你面临的问题是Linux 不允许您在进程启动后更改其父进程。如果你想要一个真正独立的进程,它需要由其他东西启动,例如 atd 或 systemd。
要解决僵尸和进程终止问题,你可以使用像 [go-reap] 这样的库(https://github.com/hashicorp/go-reap)。它提供了一个 Reaper 服务,可以自动收割孤立的子进程并报告其退出状态。
这是一个使用 go-reap 启动分离进程的示例:
<code class="go">package main import ( "context" "fmt" "os/exec" "github.com/hashicorp/go-reap" ) func main() { // Start a Reaper service to reap orphaned processes. doneCh := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) reaper := reap.NewReaper(cancel) go reaper.Run(ctx) defer reaper.Stop() // Execute a command in a detached process. cmd := exec.Command("my-long-running-command", "args") pid, err := reaper.Reap(cmd) if err != nil { fmt.Printf("Error reaping process: %v\n", err) return } fmt.Printf("PID of detached process: %v\n", pid) // Wait for the detached process to complete. exitStatus, err := reaper.WaitPid(pid) if err != nil { fmt.Printf("Error waiting for process: %v\n", err) return } fmt.Printf("Detached process exited with status: %v\n", exitStatus) // Stop the Reaper service when done. close(doneCh) }</code>
通过使用 go-reap并在进程退出时收割该进程,可以确保它不会变成僵尸,并且可以跟踪它的退出状态。
以上是如何在 Go 中分离长时间运行的进程并避免僵尸?的详细内容。更多信息请关注PHP中文网其他相关文章!