How do you get the output of a system command in Go?

假设我想在 go 程序中运行‘ ls’,并将结果存储在字符串中。在 exec 和 os 包中似乎有一些分叉进程的命令,但是它们需要 stdout 等的文件参数。有没有一种方法可以将输出作为字符串获取?

137074 次浏览

使用 exec.Run,为标准输出传递管道。从管道中读取它返回的内容。

两种选择,取决于你喜欢的范式:

  1. OS. ForkExec ()
  2. 快跑

编辑: 此答案已过时。请参阅下面的 Fatih Arslan 的回答


Use 执行官,快跑 by specifying 烟斗 as the stdout (and stderr if you want). It will return cmd, which contains an os.File in the Stdout (and Stderr) fields. Then you can read it using for example Ioutil ReadAll.

例如:

package main


import (
"exec";
"io/ioutil";
)


func main() {
if cmd, e := exec.Run("/bin/ls", nil, nil, exec.DevNull, exec.Pipe, exec.MergeWithStdout); e == nil {
b, _ := ioutil.ReadAll(cmd.Stdout)
println("output: " + string(b))
}
}

现在有一个更简单的办法:

package main


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


func main() {
out, err := exec.Command("date").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}

其中 out是标准输出。它的格式为 []byte,但是你可以很容易地用以下方法将其改为字符串:

string(out)

也可以使用 CombinedOutput()代替返回标准输出和标准错误的 Output()

执行官,指挥官

要将 stdout 和 stderr 放入单独的字符串中,可以使用如下字节缓冲区:

cmd := exec.Command("date")
var outb, errb bytes.Buffer
cmd.Stdout = &outb
cmd.Stderr = &errb
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Println("out:", outb.String(), "err:", errb.String())

我在最近版本的 GO (~ 1.11)中使用了这一点

// CmdExec Execute a command
func CmdExec(args ...string) (string, error) {


baseCmd := args[0]
cmdArgs := args[1:]


log.Debugf("Exec: %v", args)


cmd := exec.Command(baseCmd, cmdArgs...)
out, err := cmd.Output()
if err != nil {
return "", err
}


return string(out), nil
}


// Usage:
// out, err := CmdExec("ls", "/home")
cmd := exec.Command("ls", "-al")
output, _ := cmd.CombinedOutput()
fmt.Println(string(output))

或者

cmd := exec.Command(name, arg...)
stdout, err := cmd.StdoutPipe()
cmd.Stderr = cmd.Stdout
if err != nil {
return err
}
if err = cmd.Start(); err != nil {
return err
}
for {
tmp := make([]byte, 1024)
_, err := stdout.Read(tmp)
fmt.Print(string(tmp))
if err != nil {
break
}
}

如果你想要 string的输出,strings.Builder是更有效的[1]比 返回文章页面

package main


import (
"os/exec"
"strings"
)


func main() {
c, b := exec.Command("go", "version"), new(strings.Builder)
c.Stdout = b
c.Run()
print(b.String())
}
  1. Https://golang.org/pkg/bytes#buffer 线