如何在Go中获取系统命令的输出?

huangapple go评论79阅读模式
英文:

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

问题

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

英文:

Let's say I want to run 'ls' in a go program, and store the results in a string. There seems to be a few commands to fork processes in the exec and os packages, but they require file arguments for stdout, etc. Is there a way to get the output as a string?

答案1

得分: 431

现在有一种更简单的方法:

package main

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

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

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

string(out)

你也可以使用 CombinedOutput() 替代 Output(),它会返回标准输出和标准错误。

exec.Command

英文:

There is an easier way now:

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)
}

Where out is the standard output. It's in the format []byte, but you can change it to string easily with:

string(out)

You can also use CombinedOutput() instead of Output() which returns standard output and standard error.

exec.Command

答案2

得分: 60

要将标准输出和标准错误输出分别存储到不同的字符串中,您可以使用字节缓冲区,代码如下:

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())
英文:

To get both stdout and stderr into separate strings, you can use byte buffers like so:

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())

答案3

得分: 14

cmd := exec.Command("ls", "-al")
output, _ := cmd.CombinedOutput()
fmt.Println(string(output))

or

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
    }
}
英文:
cmd := exec.Command("ls", "-al")
output, _ := cmd.CombinedOutput()
fmt.Println(string(output))

or

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
    }
}

答案4

得分: 6

我使用了最近版本的GO(~1.11)

// CmdExec 执行一个命令
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
}

// 使用方法:
// out, err := CmdExec("ls", "/home")
英文:

I used this with a recent version of 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")

答案5

得分: 4

两种选择,取决于您喜欢的范例:

  1. os.ForkExec()
  2. exec.Run()
英文:

Two options, depending on the paradigm you prefer:

  1. os.ForkExec()
  2. exec.Run()

答案6

得分: 3

使用exec.Run,将Pipe传递给stdout。从返回的管道中读取。

英文:

Use exec.Run, passing Pipe for stdout. Read from the pipe that it returns.

答案7

得分: 3

如果你想要string输出,strings.Builderbytes.Buffer更高效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.String
英文:

If you are wanting string output, strings.Builder is more efficient 1 than
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())
}
  1. https://golang.org/pkg/bytes#Buffer.String

答案8

得分: 0

编辑: 这个答案已经过时了。请参考下面的 Fatih Arslan 的答案


使用 exec.Run,将 Pipe 指定为 stdout(如果需要,也可以指定为 stderr)。它会返回 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))
    }
}
英文:

Edit: This answer is obsolete. Please see Fatih Arslan's answer below.


Use exec.Run by specifying Pipe 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.

Example:

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))
	}
}

huangapple
  • 本文由 发表于 2009年12月10日 05:33:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/1877045.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定