這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
1.產生進程
package mainimport "fmt"import "io/ioutil"import "os/exec"func main() { //我們將從一個簡單的命令開始,沒有參數或者輸入,僅列印一些資訊到標準輸出資料流。exec.Command 函數協助我們建立一個表示這個外部進程的對象。 dateCmd := exec.Command("date") //.Output 是另一個協助我們處理運行一個命令的常見情況的函數,它等待命令運行完成,並收集命令的輸出。如果沒有出錯,dateOut 將擷取到日期資訊的位元組。 dateOut, err := dateCmd.Output() if err != nil { panic(err) } fmt.Println("> date") fmt.Println(string(dateOut)) //下面我們將看看一個稍複雜的例子,我們將從外部進程的stdin 輸入資料並從 stdout 收集結果。 grepCmd := exec.Command("grep", "hello") //這裡我們明確的擷取輸入/輸出管道,運行這個進程,寫入一些輸入資訊,讀取輸出的結果,最後等待程式運行結束。 grepIn, _ := grepCmd.StdinPipe() grepOut, _ := grepCmd.StdoutPipe() grepCmd.Start() grepIn.Write([]byte("hello grep\ngoodbye grep")) grepIn.Close() grepBytes, _ := ioutil.ReadAll(grepOut) grepCmd.Wait() //上面的例子中,我們忽略了錯誤偵測,但是你可以使用if err != nil 的方式來進行錯誤檢查,我們也只收集StdoutPipe 的結果,但是你可以使用相同的方法收集StderrPipe 的結果。 fmt.Println("> grep hello") fmt.Println(string(grepBytes)) //注意,當我們需要提供一個明確的命令和參數數組來產生命令,和能夠只需要提供一行命令列字串相比,你想使用通過一個字串產生一個完整的命令,那麼你可以使用 bash命令的 -c 選項: lsCmd := exec.Command("bash", "-c", "ls -a -l -h") lsOut, err := lsCmd.Output() if err != nil { panic(err) } fmt.Println("> ls -a -l -h") fmt.Println(string(lsOut))}/*產生的程式返回和我們直接通過命令列運行這些程式的輸出是相同的。$ go run spawning-processes.go> dateWed Oct 10 09:53:11 PDT 2012> grep hellohello grep> ls -a -l -hdrwxr-xr-x 4 mark 136B Oct 3 16:29 .drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..-rw-r--r-- 1 mark 1.3K Oct 3 16:28 spawning-processes.go*/
2.執行進程(有時候,我們只想用其他的(也許是非 Go 程式)來完全替代當前的 Go 進程。這時候,我們可以使用經典的 exec方法的 Go 實現)
package mainimport "syscall"import "os"import "os/exec"func main() { //在我們的例子中,我們將執行 ls 命令。Go 需要提供我們需要執行的可執行檔的絕對路徑,所以我們將使用exec.LookPath 來得到它(大概是 /bin/ls)。 binary, lookErr := exec.LookPath("ls") if lookErr != nil { panic(lookErr) } //Exec 需要的參數是切片的形式的(不是放在一起的一個大字串)。我們給 ls 一些基本的參數。注意,第一個參數需要是程式名。 args := []string{"ls", "-a", "-l", "-h"} //Exec 同樣需要使用環境變數。這裡我們僅提供當前的環境變數。 env := os.Environ() //這裡是 os.Exec 調用。如果這個調用成功,那麼我們的進程將在這裡被替換成 /bin/ls -a -l -h 進程。如果存在錯誤,那麼我們將會得到一個傳回值。 execErr := syscall.Exec(binary, args, env) if execErr != nil { panic(execErr) }}/*當我們運行程式師,它會替換為 ls。$ go run execing-processes.gototal 16drwxr-xr-x 4 mark 136B Oct 3 16:29 .drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..-rw-r--r-- 1 mark 1.3K Oct 3 16:28 execing-processes.go注意 Go 並不提供一個經典的 Unix fork 函數。通常這不是個問題,因為運行 Go 協程,產生進程和執行進程覆蓋了fork 的大多數使用用情境。*/