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

Go

Go Problem Overview


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?

Go Solutions


Solution 1 - Go

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

Solution 2 - Go

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

Solution 3 - Go

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

Solution 4 - Go

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

Solution 5 - Go

Two options, depending on the paradigm you prefer:

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

Solution 6 - Go

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

Solution 7 - Go

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

Solution 8 - Go

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmarketerView Question on Stackoverflow
Solution 1 - GoFatih ArslanView Answer on Stackoverflow
Solution 2 - GoTravis ReederView Answer on Stackoverflow
Solution 3 - GoInasa XiaView Answer on Stackoverflow
Solution 4 - GolcapraView Answer on Stackoverflow
Solution 5 - GoesmView Answer on Stackoverflow
Solution 6 - GoAndru LuvisiView Answer on Stackoverflow
Solution 7 - GoRandy Sugianto 'Yuku'View Answer on Stackoverflow
Solution 8 - GoZomboView Answer on Stackoverflow