2016-09-15 157 views
5

我想運行一個將自己置於後臺的命令(或者如果它使事情更有可能,自己在前臺模式下運行命令並將其後臺運行),並獲取pid後臺進程。我如何在Go中執行此操作?我想:golang exec後臺進程並獲取其pid

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

這將返回〜瞬間,留下SSH在後臺運行,但PID是不是運行SSH進程的PID(大概是它的父SSH進程的PID之前分叉和中背景本身) 。

如何正確執行此操作?

+0

你是什麼意思的「背景」?當你開始()你的'Cmd'時,你已經有一個單獨的子進程(有適當的'Process.Pid')同時運行到你的Go應用程序。也許你只需要從ssh標誌中刪除'-f'? –

+1

我需要該進程在我的進程退出後繼續運行。然後,我需要能夠在未來殺死後端的ssh進程,爲此我需要存儲它的pid。 – sbs

+0

嗯,實際上你是對的,如果我不等它並且退出,這個過程就會繼續。 – sbs

回答

9

你不需要任何特別的東西,只是不要告訴ssh背景本身,也不要Wait()。例如:

$ 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 
+0

你好,你的例子工作正常,但過程在完成後變成'S'模式。有沒有更好的方法來實現相同的結果?在哪裏我可以得到一個PID來檢查是否完成。在我的情況下,我不需要輸出,因爲如果成功完成,將會有包含結果的日誌文件 –

+0

如果我使用ssh連接,它會更好嗎? –