2014-04-19 78 views
10

給exec CMD我有這樣的代碼我怎樣才能在標準輸入golang

subProcess := exec.Cmd{ 
    Path: execAble, 
    Args: []string{ 
     fmt.Sprintf("-config=%s", *configPath), 
     fmt.Sprintf("-serverType=%s", *serverType), 
     fmt.Sprintf("-reload=%t", *reload), 
     fmt.Sprintf("-listenFD=%d", fd), 
    }, 
    Dir: here, 
} 
subProcess.Stdout = os.Stdout 
subProcess.Stderr = os.Stderr 
logger.Info("starting subProcess:%s ", subProcess.Args) 

if err := subProcess.Run(); err != nil { 
    logger.Fatal(err) 
} 

,然後我也os.Exit(1)停止主過程

我可以從子進程獲得輸出

但我也希望把標準輸入到

我嘗試

subProcess.Stdin = os.Stdin 

但它不起作用

回答

19

我做了一個簡單的程序(用於測試)。它讀取一個數字並寫出給定的數字。

package main 

import (
    "fmt" 
) 

func main() { 
    fmt.Println("Hello, What's your favorite number?") 
    var i int 
    fmt.Scanf("%d\n", &i) 
    fmt.Println("Ah I like ", i, " too.") 
} 

這裏是修改後的代碼

package main 

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

func main() { 
    subProcess := exec.Command("go", "run", "./helper/main.go") //Just for testing, replace with your subProcess 

    stdin, err := subProcess.StdinPipe() 
    if err != nil { 
     fmt.Println(err) //replace with logger, or anything you want 
    } 
    defer stdin.Close() // the doc says subProcess.Wait will close it, but I'm not sure, so I kept this line 

    subProcess.Stdout = os.Stdout 
    subProcess.Stderr = os.Stderr 

    fmt.Println("START") //for debug 
    if err = subProcess.Start(); err != nil { //Use start, not run 
     fmt.Println("An error occured: ", err) //replace with logger, or anything you want 
    } 

    io.WriteString(stdin, "4\n") 
    subProcess.Wait() 
    fmt.Println("END") //for debug 
} 

您有興趣瞭解這些行

stdin, err := subProcess.StdinPipe() 
if err != nil { 
    fmt.Println(err) 
} 
defer stdin.Close() 
//... 
io.WriteString(stdin, "4\n") 
//... 
subProcess.Wait() 

上述線路

  1. 我們獲得子標準輸入的說明,現在我們可以寫信給它
  2. 我們用我們的力量,我們寫一個數字
  3. 我們等待我們的子進程來完成

輸出

START
喂,什麼是你最喜歡的數字?
我也喜歡4。
END

​​

+0

你寫入子進程的標準輸入由io.WriteString – user732961

+0

但我關閉我的主進程(通過os.Exit())。所以任何代碼都無法在subProcess啓動後運行,我的問題是,如何讓os的stdin進入我的子進程。我只想通過catach ctrl-c做一些東西,但是當主進程退出時。我失去了在控制檯上的控制我開始程序 – user732961

+0

我不知道該怎麼做,但我認爲如果你捕捉到主程序(==你不os.Exit)的信號,你可以發送它們通過subProcess.Process.Signal(信號)到子進程。這個版本更容易實現(我認爲,但不知道) – mraron

2

儘管這個問題是有點老了,但這裏是我的回答:

這個問題當然是非常平臺的具體如何標準IO的處理依賴於操作系統的實現,而不是Go語言。 但是,作爲一般經驗(由於一些操作系統盛行),「你所要求的是不可能的」

在大多數現代操作系統中,您可以管理標準流(如在@ mraron的答案中),您可以將它們分開(這是守護進程如何工作),但不能將其重新分配或委派給另一個進程。

我覺得這個限制更多是因爲安全問題。仍然不時發現允許遠程代碼執行的錯誤,想象如果操作系統允許重新分配/委託STDIN/OUT,那麼由於這種漏洞,後果將是災難性的。

0

儘管您不能直接將@AlexKey寫成較早的版本,但仍然可以採取一些解決方法。如果操作系統可以防止你管你自己的標準流誰在乎你只需要2個通道和2個夠程

var stdinChan chan []byte 
var stdoutChan chan []byte 

//when something happens in stdout of your code just pipe it to stdout chan 
stdoutChan<-somehowGotDataFromStdOut 

,那麼你需要兩個funcs中,因爲我之前

func Pipein(){ 
    for { 
     stdinFromProg.Write(<-stdInChan) 
    } 
} 

提到對於stdout

同樣的想法