我正在尝试在 Go 中“分叉”一个后台进程——在 Mac 和 Linux 上完美运行,但在 Windows 上关闭终端时就会终止

Ser*_*gey 6 windows background-process go windows-console

考虑这个简单的 Go 程序,它演示了在 Go 中“分叉”后台进程的标准方法。当它运行时,它应该立即将自己发送到后台,在那里每秒将递增整数写入output.txt一次。它会一直运行,直到您手动杀死它。

这个程序在 Mac 和 Linux 上完美运行,但在 Windows 上有一个奇怪的行为:它似乎有效,因为我立即再次收到命令提示符,并且我的进程确实在后台运行并将这些整数写入 output.txt。但是,当我关闭终端窗口时,后台进程会被终止。

标准 cmd.exe 和使用 PowerShell 的新式 Windows 终端都会出现此问题。在 Mac 和 Linux 上不存在这样的问题,在终端关闭、ssh 注销等情况下它可以很好地生存。

我尝试使用 cmd.SysProcAttr 设置 syscall.CREATE_NEW_PROCESS_GROUP,但这没有什么区别。

我的问题是,当终端关闭时,是什么导致它在 Windows 上死掉以及如何让它停止?

package main

import (
    "fmt"
    "os"
    "os/exec"
    "time"
)

var childEnv = "__IS_CHILD"

func main() {
    if os.Getenv(childEnv) == "" {
        fork()
        os.Exit(0)
    }

    for i := 0; ; i++ {
        fmt.Println(i)
        time.Sleep(time.Second)
    }
}

func fork() {
    outfile, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }

    cmd := exec.Command(os.Args[0])
    cmd.Env = append(os.Environ(), fmt.Sprintf("%v=%v", childEnv, 1))
    cmd.Stdout = outfile
    cmd.Stderr = outfile

    if err = cmd.Start(); err != nil {
        panic(err)
    }
}

Run Code Online (Sandbox Code Playgroud)

Ser*_*gey 3

我想到了。我只需要添加下面的代码,那么当终端窗口关闭时,分离的进程就不会终止。

cmd.SysProcAttr = &syscall.SysProcAttr{
    CreationFlags: windows.CREATE_NEW_PROCESS_GROUP | windows.DETACHED_PROCESS,
}
Run Code Online (Sandbox Code Playgroud)

这里有关于 Windows 进程创建标志的文档:https ://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags