Backend Development 21 min read

A Quick Guide to Go's os/exec Package: Running External Commands and Real‑World Use Cases

This article introduces Go's built‑in os/exec package, explains its exported types and methods, demonstrates how to run commands synchronously or in the background, capture output, handle pipes, environment variables, working directories, and shows a practical case study using the tempredis library to start a Redis server programmatically.

Go Programming World
Go Programming World
Go Programming World
A Quick Guide to Go's os/exec Package: Running External Commands and Real‑World Use Cases

The Go os/exec package provides a simple way to start external programs such as redis-server , ls , or any shell command, offering functions like Command , CommandContext , Run , Start , Output , and CombinedOutput .

Typical usage starts with creating a command object, for example: cmd := exec.Command("echo", "Hello, World!") err := cmd.Run() which runs the command and waits for it to finish, logging any error.

Running a command in the background uses Start followed by Wait or by reading from pipes. The Run method is equivalent to Start + Wait :

func (c *Cmd) Run() error {
    if err := c.Start(); err != nil {
        return err
    }
    return c.Wait()
}

Context‑aware execution is possible with exec.CommandContext , allowing automatic cancellation on timeout:

ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
cmd := exec.CommandContext(ctx, "sleep", "5")
if err := cmd.Run(); err != nil {
    log.Fatalf("Command failed: %v", err)
}

To capture output, use Output (stdout only) or CombinedOutput (stdout + stderr):

cmd := exec.Command("echo", "Hello, World!")
output, err := cmd.Output()
fmt.Println(string(output))

Standard streams can be redirected by assigning to cmd.Stdout and cmd.Stderr , or by using StdoutPipe , StderrPipe , and StdinPipe for custom handling, such as feeding data via an io.Reader :

cmd := exec.Command("grep", "hello")
cmd.Stdin = bytes.NewBufferString("hello world\nhi there\n")
output, _ := cmd.Output()
fmt.Println(string(output))

Environment variables are accessed with cmd.Environ() and set via the Env slice:

cmd := exec.Command("printenv", "ENV_VAR")
cmd.Env = append(cmd.Env, "ENV_VAR=HelloWorld")
output, _ := cmd.Output()
fmt.Println(string(output))

Pipes can be built manually using StdoutPipe and assigning the resulting reader to another command's Stdin , or by invoking a shell with bash -c to use shell operators like | :

cmd := exec.Command("bash", "-c", "echo 'hello world' | grep hello")
output, _ := cmd.Output()
fmt.Println(string(output))

The working directory is set with cmd.Dir , and exit status can be inspected via exec.ExitError after a failed Run call.

Finding an executable in the system PATH is done with exec.LookPath :

path, err := exec.LookPath("ls")
fmt.Printf("ls is available at %s\n", path)

A practical example is the third‑party tempredis library, which uses os/exec to start a temporary Redis server. The library defines a Config map, a Server struct that holds an *exec.Cmd , and methods such as Start , start , ready , waitFor , Stdout , Stderr , Term , and Kill . It launches redis-server - , writes configuration via the command's stdin, and monitors stdout for readiness strings like "The server is now ready to accept connections".

In summary, os/exec is a versatile tool for process management in Go, suitable for backend services, testing, and automation tasks, and its patterns are demonstrated both in simple snippets and in a real‑world library that starts Redis instances on demand.

RedisGoProcess ManagementTutorialos/execexternal commandstempredis
Go Programming World
Written by

Go Programming World

Mobile version of tech blog https://jianghushinian.cn/, covering Golang, Docker, Kubernetes and beyond.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.