在go程序中執行系統命令需使用os/exec包,其核心步驟為:1.通過exec.command創建命令對象并調用run或output方法執行;2.注意參數應分開傳遞而非整串傳入;3.獲取輸出時可用output()或管道分別捕獲stdout和stderr;4.需要輸入時可通過stdinpipe寫入數據;5.靈活控制可通過設置cmd字段如工作目錄、環境變量等實現。
在寫 Go 程序的時候,有時候需要執行一些系統命令,比如調用 ls、grep 或者你自己寫的腳本。這時候就可以用標準庫里的 os/exec 包來搞定。它提供了一種安全又方便的方式來運行外部程序,并且可以控制輸入輸出。
最基本的用法:執行一個命令
調用外部命令最簡單的辦法就是使用 exec.Command() 創建一個命令對象,然后調用它的方法去執行。
比如,我們想執行 ls -l:
立即學習“go語言免費學習筆記(深入)”;
cmd := exec.Command("ls", "-l") err := cmd.Run() if err != nil { log.Fatal(err) }
這段代碼會直接運行 ls -l 并把結果打印到終端。注意參數是分開傳進去的,不是整個字符串,這是 exec.Command 的要求。
常見錯誤提醒:
- 命令拼錯了或者路徑不對,會導致找不到命令;
- 參數順序搞反了,可能不會報錯但結果不對;
- 沒有處理錯誤,程序可能會靜默失敗。
獲取命令輸出內容
很多時候我們不只是想讓命令跑一下,而是要拿到它的輸出,比如你調用 whoami 想知道當前用戶是誰。
這個時候要用 cmd.Output():
cmd := exec.Command("whoami") out, err := cmd.Output() if err != nil { log.Fatal(err) } fmt.Println("當前用戶是:", string(out))
這樣就能把命令的標準輸出拿到手,是個字節數組,轉成字符串就可用了。
注意事項:
- 如果命令出錯(比如返回非0狀態碼),Output() 也會報錯;
- 如果你想分別獲取 stdout 和 stderr,需要用 cmd.StdoutPipe() 和 cmd.StderrPipe();
- 輸出的內容末尾通常會帶換行符,可以用 strings.TrimSpace() 處理一下。
給命令傳入輸入內容
有些命令需要你從標準輸入給它喂數據,比如 grep hello 后面不跟文件名,就會等你輸入。
Go 里可以通過 stdin 管道實現這個功能:
cmd := exec.Command("grep", "hello") stdin, err := cmd.StdinPipe() if err != nil { log.Fatal(err) } go func() { defer stdin.Close() io.WriteString(stdin, "hello worldn") }() out, _ := cmd.Output() fmt.Println(string(out))
這里創建了一個管道,然后在一個 goroutine 里往里面寫數據,模擬用戶輸入。這種方式適合做自動化測試或集成腳本。
更靈活的控制方式
如果你需要更細粒度地控制命令的執行過程,比如設置環境變量、工作目錄,或者捕獲錯誤輸出,可以手動配置 *exec.Cmd 的字段:
cmd := exec.Command("sh", "-c", "echo $TEST_ENV") cmd.Dir = "/tmp" // 設置工作目錄 cmd.Env = []string{"TEST_ENV=hello"} // 設置環境變量 // 單獨捕獲標準錯誤 stderr, _ := cmd.StderrPipe() go func() { buf := make([]byte, 1024) for { n, err := stderr.Read(buf) if n > 0 { fmt.Println("stderr:", string(buf[:n])) } if err != nil { break } } }() cmd.Run()
這種寫法雖然復雜點,但能讓你對整個執行過程有完全掌控權。
基本上就這些。剛上手的時候別怕試錯,多看看文檔和例子,慢慢就能熟練掌握 os/exec 的各種用法了。