Run, Pipe, and Time Out Processes
Capture a command's output, read an exit code, wire one command's stdout into another like a shell pipeline, and kill a slow command when a context deadline passes.
package main
import (
"bytes"
"context"
"errors"
"fmt"
"os/exec"
"time"
)
func main() {
// 1) Run a command and capture stdout.
out, _ := exec.Command("uname", "-s").Output()
fmt.Printf("kernel: %s", out) // kernel: Darwin (or Linux)
// 2) A non-zero exit surfaces as *exec.ExitError.
err := exec.Command("false").Run()
var ee *exec.ExitError
if errors.As(err, &ee) {
fmt.Println("false exited:", ee.ExitCode()) // false exited: 1
}
// 3) A pipeline: `ls -1 /` | `wc -l`, stdout wired to stdin.
ls := exec.Command("ls", "-1", "/")
wc := exec.Command("wc", "-l")
wc.Stdin, _ = ls.StdoutPipe()
var count bytes.Buffer
wc.Stdout = &count
wc.Start()
ls.Run()
wc.Wait()
fmt.Print("entries in /: ", count.String())
// 4) Timeout: the context deadline kills the process.
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
defer cancel()
err = exec.CommandContext(ctx, "sleep", "5").Run()
fmt.Println("sleep result:", err) // sleep result: signal: killed
fmt.Println("deadline hit:", errors.Is(ctx.Err(), context.DeadlineExceeded))
// deadline hit: true
}Save the code as main.go and run it:
go run main.goExpected output:
kernel: Linux
false exited: 1
entries in /: 24
sleep result: signal: killed
deadline hit: truekernel prints Linux or Darwin, and the entry count for / depends on your machine.