golang exec后台进程并获取其pid

golang exec后台进程并获取其pid,go,exec,pid,Go,Exec,Pid,情况: cmd := exec.Command("ssh", "-i", keyFile, "-o", "ExitOnForwardFailure yes", "-fqnNTL", fmt.Sprintf("%d:127.0.0.1:%d", port, port), fmt.Sprintf("%s@%s", serverUser, serverIP)) cmd.Start() pid := cmd.Process.Pid cmd.Wait() 我想运行一个命令,将其自身置于后台。如果这样做更

情况:

cmd := exec.Command("ssh", "-i", keyFile, "-o", "ExitOnForwardFailure yes", "-fqnNTL", fmt.Sprintf("%d:127.0.0.1:%d", port, port), fmt.Sprintf("%s@%s", serverUser, serverIP))
cmd.Start()
pid := cmd.Process.Pid
cmd.Wait()
我想运行一个命令,将其自身置于后台。如果这样做更可行,那么我将在前台运行该命令,并亲自将其带到后台

问题:

cmd := exec.Command("ssh", "-i", keyFile, "-o", "ExitOnForwardFailure yes", "-fqnNTL", fmt.Sprintf("%d:127.0.0.1:%d", port, port), fmt.Sprintf("%s@%s", serverUser, serverIP))
cmd.Start()
pid := cmd.Process.Pid
cmd.Wait()
当进程在后台运行时:如何使用Go获取它的
pid

我尝试了以下方法:

cmd := exec.Command("ssh", "-i", keyFile, "-o", "ExitOnForwardFailure yes", "-fqnNTL", fmt.Sprintf("%d:127.0.0.1:%d", port, port), fmt.Sprintf("%s@%s", serverUser, serverIP))
cmd.Start()
pid := cmd.Process.Pid
cmd.Wait()

这会立即返回,并让
ssh
在后台运行。但是它的
pid
不是运行
ssh
进程的
pid
。此外,它是父进程的
pid
,在它自身分叉和后台处理之前。

你不需要任何特殊的东西,只要不告诉ssh自己后台处理,也不必等待它。例如:

$ cat script.sh
#!/bin/sh
sleep 1
echo "I'm the script with pid $$"
for i in 1 2 3; do
        sleep 1
        echo "Still running $$"
done
$ cat proc.go
package main

import (
       "log"
       "os"
       "os/exec"
)

func main() {
     cmd := exec.Command("./script.sh")
     cmd.Stdout = os.Stdout
     err := cmd.Start()
     if err != nil {
        log.Fatal(err)
     }
     log.Printf("Just ran subprocess %d, exiting\n", cmd.Process.Pid)
}
$ go run proc.go
2016/09/15 17:01:03 Just ran subprocess 3794, exiting
$ I'm the script with pid 3794
Still running 3794
Still running 3794
Still running 3794

@Mostafa Hussein,可以使用goroutine等待,管理流程

function main()
    cmd := exec.Command( "shell.sh" )
    err := cmd.Start()
    if err != nil {
        return err
    }
    pid := cmd.Process.Pid
    // use goroutine waiting, manage process
    // this is important, otherwise the process becomes in S mode
    go func() { 
        err = cmd.Wait()
        fmt.Printf("Command finished with error: %v", err)
    }()
    return nil
}

你说的“背景”是什么意思?当您使用
Start()
您的
Cmd
时,您已经有了一个单独的子进程(带有适当的
process.Pid
)同时运行到您的Go应用程序。也许您只需要从ssh标志中删除
-f
?我需要进程在我的go进程退出后继续运行。然后我需要能够在将来终止后台ssh进程,为此我需要存储其pid。嗯,实际上你是对的,如果我不等待它并退出,进程将继续。您好,您的示例工作正常,但进程在完成后将变为
S
模式。有没有更好的方法达到同样的效果?在那里我可以得到一个pid,以检查是否完成。在我的情况下,我不需要输出,因为如果成功完成,将有包含结果的日志文件