我需要在Go中启动一个新的stream程,并具有以下要求:
这是一个尝试:
var attr = os.ProcAttr { Dir: "/bin", Env: os.Environ(), Files: []*os.File{ os.Stdin, "stdout.log", "stderr.log", }, } process, err := os.StartProcess("sleep", []string{"1"}, &attr)
这工作正常,但从要求有以下缺点:
只有在简化事情的情况下才需要在Linux上运行。
这里是你的例子的工作版本(我没有检查过程ID是实际上在哪里设置的)
package main import "fmt" import "os" import "syscall" const ( UID = 501 GUID = 100 ) func main() { // The Credential fields are used to set UID, GID and attitional GIDS of the process // You need to run the program as root to do this var cred = &syscall.Credential{ UID, GUID, []uint32{} } // the Noctty flag is used to detach the process from parent tty var sysproc = &syscall.SysProcAttr{ Credential:cred, Noctty:true } var attr = os.ProcAttr{ Dir: ".", Env: os.Environ(), Files: []*os.File{ os.Stdin, nil, nil, }, Sys:sysproc, } process, err := os.StartProcess("/bin/sleep", []string{"/bin/sleep", "100"}, &attr) if err == nil { // It is not clear from docs, but Realease actually detaches the process err = process.Release(); if err != nil { fmt.Println(err.Error()) } } else { fmt.Println(err.Error()) } }
我发现,似乎跨平台的工作是用一个特殊的标志重新运行程序。 在你的主程序中,检查这个标志。 如果在启动时出现,则处于“分叉”状态。 如果不存在,用标志重新运行命令。
func rerunDetached() error { cwd, err := os.Getwd() if err != nil { return err } args := append(os.Args, "--detached") cmd := exec.Command(args[0], args[1:]...) cmd.Dir = cwd err = cmd.Start() if err != nil { return err } cmd.Process.Release() return nil }
这将简单地用确切的参数重新运行你的进程,并追加 – 附加到参数。 当你的程序启动时,检查--detached
标志来知道你是否需要调用rerunDetached
。 这就像一个可怜的男人fork()
,将跨不同的操作系统。