Go exec command
last modified April 11, 2024
In this article we show how to execute shell commands and programs in Golang.
The Run
function starts the specified command and waits for it to
complete, while the Start
starts the specified command but does not
wait for it to complete; we need to use Wait
with Start
.
Go os/exec
The os/exec
package runs external commands. It wraps
os.StartProcess
to make it easier to remap stdin and stdout,
connect I/O with pipes, and do other adjustments.
$ go version go version go1.22.2 linux/amd64
We use Go version 1.22.2.
Go exec program
The Run
starts the specified command and waits for it to complete.
package main import ( "log" "os/exec" ) func main() { cmd := exec.Command("firefox") err := cmd.Run() if err != nil { log.Fatal(err) } }
In the code example, we execute the Firefox browser.
Go exec.Command
The Command
returns the Cmd struct to execute the specified
program with the given arguments. The first parameter is the program to be run;
the other arguments are parameters to the program.
package main import ( "bytes" "fmt" "log" "os/exec" "strings" ) func main() { cmd := exec.Command("tr", "a-z", "A-Z") cmd.Stdin = strings.NewReader("and old falcon") var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() if err != nil { log.Fatal(err) } fmt.Printf("translated phrase: %q\n", out.String()) }
In the code example, we transform the input via the tr
command.
cmd := exec.Command("tr", "a-z", "A-Z")
The tr
standard Linux command translates, squeezes, and/or deletes
characters from standard input, writing to standard output. In our case, we
transform lowercase letters to uppercase ones.
cmd.Stdin = strings.NewReader("and old falcon")
Through the Stdin
field, we pass a string to the command as its
input.
var out bytes.Buffer cmd.Stdout = &out
The output of the program will be written to the bytes buffer.
$ go run command.go translated phrase: "AND OLD FALCON"
Go exec command with multiple args
We can pass multiple arguments to the exec.Command
.
package main import ( "fmt" "os/exec" ) func main() { prg := "echo" arg1 := "there" arg2 := "are three" arg3 := "falcons" cmd := exec.Command(prg, arg1, arg2, arg3) stdout, err := cmd.Output() if err != nil { fmt.Println(err.Error()) return } fmt.Print(string(stdout)) }
The example runs the echo
command with three arguments.
$ go run multiple_args.go there are three falcons
Go exec command capture output
The Output
runs the command and returns its standard output.
package main import ( "fmt" "log" "os/exec" ) func main() { out, err := exec.Command("ls", "-l").Output() if err != nil { log.Fatal(err) } fmt.Println(string(out)) }
The example captures the output of the ls
command and prints it.
Go cmd.StdinPipe
The pipe allows us to send the output of one command to another. The
StdinPipe
returns a pipe that will be connected to the command's
standard input when the command starts.
package main import ( "fmt" "io" "log" "os/exec" ) func main() { cmd := exec.Command("cat") stdin, err := cmd.StdinPipe() if err != nil { log.Fatal(err) } go func() { defer stdin.Close() io.WriteString(stdin, "an old falcon") }() out, err := cmd.CombinedOutput() if err != nil { log.Fatal(err) } fmt.Printf("%s\n", out) }
In the code example, we write a string to the standard input inside a goroutine.
cmd := exec.Command("cat")
The cat
command concatenates the given files to the standard
output. When no file is given, or with -, the command reads standard input and
prints it to standard output.
stdin, err := cmd.StdinPipe()
We get the standard input pipe of the cat
command.
go func() { defer stdin.Close() io.WriteString(stdin, "an old falcon") }()
Inside the goroutine, we write a string to the stdin pipe.
$ go run stdinpipe.go an old falcon
Go cmd.StdoutPipe
The StdoutPipe
returns a pipe that will be connected to the
command's standard output when the command starts.
package main import ( "fmt" "io/ioutil" "log" "os/exec" "strings" ) func upper(data string) string { return strings.ToUpper(data) } func main() { cmd := exec.Command("echo", "an old falcon") stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } if err := cmd.Start(); err != nil { log.Fatal(err) } data, err := ioutil.ReadAll(stdout) if err != nil { log.Fatal(err) } if err := cmd.Wait(); err != nil { log.Fatal(err) } fmt.Printf("%s\n", upper(string(data))) }
The example reads the output of the echo
command through the pipe
and transforms it into uppercase letters.
cmd := exec.Command("echo", "an old falcon")
The command to run is the echo
command with a single string
argument.
stdout, err := cmd.StdoutPipe()
We get the standard output pipe.
if err := cmd.Start(); err != nil { log.Fatal(err) }
The command is executed with the Start
function; it does not wait
wait for it to complete.
data, err := ioutil.ReadAll(stdout)
We read the data from the pipe.
if err := cmd.Wait(); err != nil { log.Fatal(err) }
The Wait
waits for the command to exit and waits for any copying to
stdin or copying from stdout or stderr to complete. It closes the pipe after
seeing the command exit.
$ go run stdoutpipe.go AN OLD FALCON
Source
In this article we have executed external commands in Golang.
Author
List all Go tutorials.