Golang background process: start, monitor, and wait with os/exec

Golang start process and spawn with os/exec Start Wait and Run; CommandContext timeouts; goroutines channels WaitGroup for golang background jobs; go run in background vs shell; wait golang patterns.

Published

Updated

Read time 4 min read

Reviewed byDeepak Prasad

Golang background process: start, monitor, and wait with os/exec

People searching for golang background process, golang process monitor, golang background, golang start process, golang background jobs, golang process, golang spawn process, or wait golang usually want one of two things: run an external program from Go and wait for it (os/exec), or run your own work concurrently (goroutines, channels, sync.WaitGroup). This page focuses on child processes with exec.Cmd, when to use Start/Wait vs Run, how CommandContext ties processes to timeouts, and how goroutines fit golang background jobs. For go run in background or golang run main, that is normally a shell concern (&, nohup, systemd), not a special Go keyword. For goroutine basics see goroutines in Go; for WaitGroup details see WaitGroup tutorial.

Tested with Go 1.24 on Linux.


Golang spawn process: exec.Command, Start, Wait, and Run

To golang start process or golang spawn process another executable, use exec.Command (or CommandContext). Typical flow:

  1. Build cmd := exec.Command("name", "args…").
  2. Call cmd.Start() to create the child without blocking until exit.
  3. Optionally do other work.
  4. Call cmd.Wait() to block until the child exits and reap it.

cmd.Run() is shorthand for Start followed by Wait on the same goroutine—it blocks the whole time.

go
package main

import (
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("sleep", "0")
	if err := cmd.Start(); err != nil {
		panic(err)
	}
	fmt.Printf("PID %d\n", cmd.Process.Pid)
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
	fmt.Println("Process completed.")
}
text
PID 140495
Process completed.

The PID value changes every run; only the flow matters.

After a successful Wait, inspect cmd.ProcessState for exit information (for example Success() or platform-specific exit codes).


Timeouts and cancellation: exec.CommandContext

For a golang process monitor style control plane—start work but abort if it runs too long—attach a context.Context:

go
package main

import (
	"context"
	"fmt"
	"os/exec"
	"time"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
	defer cancel()
	cmd := exec.CommandContext(ctx, "sleep", "10")
	if err := cmd.Start(); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		fmt.Println("wait:", err)
	}
}
text
wait: signal: killed

When the context hits its deadline, the child is stopped; Wait returns an error you should handle (signal, context.DeadlineExceeded, etc., depending on platform and timing).


Golang background jobs: goroutines, channels, and WaitGroup

If you need your program to keep doing other work while a subprocess runs, run Start (and later Wait) inside a goroutine and signal completion on a channel, or count jobs with sync.WaitGroup. That matches golang background and golang background jobs intent: your process stays responsive while children or tasks finish.

go
package main

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

func main() {
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		cmd := exec.Command("sleep", "0")
		if err := cmd.Start(); err != nil {
			fmt.Println("start:", err)
			return
		}
		fmt.Printf("child PID %d\n", cmd.Process.Pid)
		if err := cmd.Wait(); err != nil {
			fmt.Println("wait:", err)
		}
	}()
	wg.Wait()
	fmt.Println("all children finished")
}
text
child PID 140735
all children finished

The child PID is assigned by the operating system and will differ each run.

A channel-based variant matches the “done channel” pattern from the older draft: the goroutine sends cmd.Wait()’s error (or nil) on done and the main goroutine receives once.


wait golang: what blocks where

API What it waits for
cmd.Wait() One specific child exec.Cmd
wg.Wait() All goroutines that called Done() after Add
receiving from a channel Whatever send signals completion

Wait must run once per successful Start for that Cmd (see Cmd documentation).


go run in background and golang run main (terminal, not the language)

go run in background almost always means the shell started go run with &, nohup, disown, or a service manager. Go the language does not define “background go run”; your binary is already one OS process. To detach a compiled binary as a service, use systemd, supervisor, or container orchestration—not a special go flag.


Summary

For golang background process and golang process monitor scenarios that wrap other programs, use os/exec: exec.Command to spawn, Start to launch without blocking until exit, Wait to join and collect status, or Run when you want a single blocking call. exec.CommandContext adds timeouts and cancellation, which is how you stop stuck children cleanly. For golang background jobs inside your app, combine Start/Wait with goroutines, channels, or sync.WaitGroup. wait golang in search maps to these Wait APIs, not a single global primitive. go run in background belongs to the shell or process supervisor, not to exec by itself.


References


Frequently Asked Questions

1. In Go does exec.Cmd Start run the program in the background?

Start launches the child process without blocking until it exits. Your Go code usually continues until you call Wait or Run. The child is a separate OS process; your goroutine is still responsible for waiting if you need completion or status.

2. What is the difference between Run and Start plus Wait?

Run starts the command and blocks until it finishes, combining Start and Wait. Start plus Wait splits launch and join so you can do other work between them on the same goroutine, or move Wait to another goroutine.

3. How do I stop a child process from a timeout?

Use exec.CommandContext with a context that times out or is cancelled; Wait typically returns an error like context deadline exceeded or signal killed when the runtime stops the child.

4. Is go run in background the same as a golang background process?

go run in background usually means your shell ran the compiler in the background with & or nohup. Inside a Go program you spawn other programs with os/exec, not with go run.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …