2015-01-16 27 views
-1

所以我想在Go中創建一個命令shell。我的目標是在我正在考慮編寫的便攜式系統工具中使用它的功能。我認爲一個很好的起點是能夠演示運行系統命令並允許用戶與系統shell進行交互的基礎知識。如何在Go中使用我的系統的命令shell?

回答

1

我已經寫就這一段時間以前這表明幾種方法可以做到這一點,以及如何輸出/輸入,可以從圍棋應用程序中管理的博客文章。

http://www.darrencoxall.com/golang/executing-commands-in-go/

的密鑰數據包,以看就是os/exec並專門Command功能。

http://godoc.org/os/exec#Command

+0

正確的錢。 ox.exec包正是我所需要的。和漂亮的博客文章!我在那裏看到一些好東西,我需要寫入我的代碼。 – lee8oi

0

我有這樣的解決方案!我實際上已經發布在gist.github.com/lee8oi/a8a90f559fe48355f800

它是一個很好的小演示,它使用Go的os/exec包來直接將輸入/輸出/錯誤輸出到命令實例。當「bash」運行時,你會坐在一個非常簡單的提示符下。你可以像使用bash一樣進行交互(但仍然非常簡單)。當您運行常規命令時,將顯示輸出,然後命令將退出(如使用「ping」)。我認爲這將是一個很好的起點,可以用來與Go中的系統shell進行交互。

package main 

import (
    "bufio" 
    "fmt" 
    "io" 
    "log" 
    "os" 
    "os/exec" 
    "sync" 
) 

func getPipes(c *exec.Cmd) (inp io.Writer, outp, errp io.Reader) { 
    var err error 
    if inp, err = c.StdinPipe(); err != nil { 
     log.Fatal(err) 
    } 
    if outp, err = c.StdoutPipe(); err != nil { 
     log.Fatal(err) 
    } 
    if errp, err = c.StderrPipe(); err != nil { 
     log.Fatal(err) 
    } 
    return 
} 

func pipe(wg *sync.WaitGroup, inp io.Reader, outp io.Writer) { 
    if wg != nil { 
     defer wg.Done() 
    } 
    r := bufio.NewReader(inp) 
    for { 
     c, err := r.ReadByte() 
     if err != nil { 
      return 
     } 
     fmt.Fprintf(outp, "%s", string(c)) 
    } 
} 

func Command(args ...string) { 
    var cmd *exec.Cmd 
    var wg sync.WaitGroup 
    if len(args) > 1 { 
     cmd = exec.Command(args[0], args[1:]...) 
    } else { 
     cmd = exec.Command(args[0]) 
    } 
    inp, outp, errp := getPipes(cmd) 
    wg.Add(1) 
    go pipe(&wg, errp, os.Stderr) 
    wg.Add(1) 
    go pipe(&wg, outp, os.Stdout) 
    go pipe(nil, os.Stdin, inp) 
    if err := cmd.Start(); err != nil { 
     log.Fatal("start ", err) 
    } 
    wg.Wait() 
} 

func main() { 
    Command("bash") 
    Command("date") 
    Command("echo", "some text") 
    Command("ping", "-c 3", "www.google.com") 
} 
+0

我還是不知道是否有在堆棧溢出問題的錯誤/回答日期,如果你確實回答了自己在不到一秒鐘。兩者都在23:32:47Z。 – siritinga

+0

爲您編寫的代碼審查:如果^ D脫離shell,這將給出一個零指針異常。使用'interface {}'很奇怪,只需使用'io.Reader'和'io.Writer'。應該檢查來自'StdinPipe *'的錯誤,以及來自'Wait'的錯誤。 runPipe'過於複雜 - 你可以用'io.Copy'替換它。 –

+0

謝謝尼克。好東西。說實話,它只是爲了在Go中使用shell的一些黑客代碼。我確實檢查過Std {out,err,in} Pipe()函數,它們只是從不觸發。但爲了完整性,我可以把它們放回去。考慮到您的建議,我會再次檢查代碼。再次感謝。你說的比迄今爲止的整個G + Go社區更有用。 – lee8oi