【发布时间】:2010-12-25 00:35:37
【问题描述】:
假设我想在 go 程序中运行 'ls',并将结果存储在字符串中。在 exec 和 os 包中似乎有一些 fork 进程的命令,但它们需要 stdout 等的文件参数。有没有办法将输出作为字符串获取?
【问题讨论】:
标签: go
假设我想在 go 程序中运行 'ls',并将结果存储在字符串中。在 exec 和 os 包中似乎有一些 fork 进程的命令,但它们需要 stdout 等的文件参数。有没有办法将输出作为字符串获取?
【问题讨论】:
标签: go
如果你想要string 输出,strings.Builder 比 [1] 更有效
bytes.Buffer:
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())
}
【讨论】:
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
}
}
【讨论】:
现在有一个更简单的方法:
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(),后者返回标准输出和标准错误。
【讨论】:
我在最新版本的 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")
【讨论】:
编辑:此答案已过时。请参阅下面的Fatih Arslan's answer。
通过将Pipe 指定为标准输出来使用exec.Run(如果需要,还可以使用标准错误)。它将返回 cmd,其中在 Stdout(和 Stderr)字段中包含 os.File。然后您可以使用例如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))
}
}
【讨论】:
exec 包不再存在 afaik,ioutil.ReadAll() 不再接受 cmd.Stdout 但 cmd.Stdin,因此关于这个答案的几乎所有内容都是错误和过时的。
要将 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())
【讨论】:
使用exec.Run,将管道传递给标准输出。从它返回的管道中读取。
【讨论】:
两个选项,取决于您喜欢的范例:
【讨论】: