Golang: exec.Command() examples

stat-bin.go

$ cat stat-bin.go
package main

import (
        "bytes"
        "log"
        "os"
        "os/exec"
        "strings"
)

func main() {
        folder := "/bin"
        if os.Getenv("FORCE_ERROR") == "1" {
                folder = "/does-not-exist"
        }
        var stdout bytes.Buffer
        var stderr bytes.Buffer
        cmd := exec.Command("stat", folder)
        cmd.Stdout = &stdout
        cmd.Stderr = &stderr
        if err := cmd.Run(); err != nil {
                log.Fatalf("error: 'cmd.Run()' failed: %v -> %s", err, stderr.String())
        }
        lines := strings.Split(stdout.String(), "\n")
        for _, line := range lines {
                if line == "" {
                        continue
                }
                log.Print(line)
        }
}

Successful execution:

$ go run stat-bin.go
2024/12/11 17:33:29   File: /bin -> usr/bin
2024/12/11 17:33:29   Size: 7           Blocks: 0          IO Block: 4096   symbolic link
2024/12/11 17:33:29 Device: fd03h/64771d        Inode: 132         Links: 1
2024/12/11 17:33:29 Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
2024/12/11 17:33:29 Access: 2024-12-10 19:07:43.216006371 +0000
2024/12/11 17:33:29 Modify: 2023-06-10 10:38:34.042107526 +0000
2024/12/11 17:33:29 Change: 2023-06-10 10:38:34.042107526 +0000
2024/12/11 17:33:29  Birth: 2023-06-10 10:38:34.042107526 +0000

Failed execution:

$ FORCE_ERROR=1 go run stat-bin.go
2024/12/11 17:33:31 error: 'cmd.Run()' failed: exit status 1 -> stat: cannot statx '/does-not-exist': No such file or directory
exit status 1

head-5-cat-n.go

$ cat head-5-cat-n.go
package main

import (
        "log"
        "os"
        "os/exec"
)

func main() {
        buf, err := os.ReadFile("head-5-cat-n.go")
        if err != nil {
                log.Fatal("error: 'os.ReadFile()' failed", "err", err)
        }
        cmd := exec.Command("/bin/bash", "-c", "head -n 5 | cat -n")
        cmd.Stdout = os.Stdout
        cmd.Stderr = nil // == /dev/null
        stdin, err := cmd.StdinPipe()
        if err != nil {
                log.Fatal("error: 'cmd.StdinPipe()' failed: %v", err)
        }
        if err := cmd.Start(); err != nil {
                log.Fatal("error: 'cmd.Start()' failed: %v", err)
        }
        _, err = stdin.Write([]byte(buf))
        if err != nil {
                log.Fatal("error: 'stdin.Write()' failed: %v", err)
        }
        err = stdin.Close()
        if err != nil {
                log.Fatal("error: 'stdin.Close()' failed: %v", err)
        }
        err = cmd.Wait()
        if err != nil {
                log.Fatal("error: 'cmd.Wait()' failed: %v", err)
        }
}

Execution:

$ go run head-5-cat-n.go
     1  package main
     2
     3  import (
     4          "log"
     5          "os"

cat-pipe.go

$ cat cat-pipe.go
package main

import (
        "bufio"
        "fmt"
        "log"
        "os/exec"
        "time"
)

func main() {
        cmd := exec.Command("cat", "-n")
        cmd.Stderr = nil // == /dev/null
        stdin, err := cmd.StdinPipe()
        if err != nil {
                log.Fatal("error: 'cmd.StdinPipe()' failed: %v", err)
        }
        stdout, err := cmd.StdoutPipe()
        if err != nil {
                log.Fatal("error: 'cmd.StdoutPipe()' failed: %v", err)
        }
        if err := cmd.Start(); err != nil {
                log.Fatal("error: 'cmd.Start()' failed: %v", err)
        }
        go func() {
                for i := 0; i < 5; i++ {
                        if i > 0 {
                                time.Sleep(time.Second)
                        }
                        _, err = stdin.Write([]byte(fmt.Sprintf("**** %d ****\n", i)))
                        if err != nil {
                                log.Fatal("error: 'stdin.Write()' failed: %v", err)
                        }
                }
                err = stdin.Close()
                if err != nil {
                        log.Fatal("error: 'stdin.Close()' failed: %v", err)
                }
        }()
        scanner := bufio.NewScanner(stdout)
        for scanner.Scan() {
                line := scanner.Text()
                log.Print(">>> " + line)
        }
        if err := scanner.Err(); err != nil {
                log.Fatal("error: 'scanner.Err()' is not nil: %v", err)
        }
        err = cmd.Wait()
        if err != nil {
                log.Fatal("error: 'cmd.Wait()' failed: %v", err)
        }
}

Execution:

$ go run cat-pipe.go
2024/12/11 17:39:44 >>>      1  **** 0 ****
2024/12/11 17:39:45 >>>      2  **** 1 ****
2024/12/11 17:39:46 >>>      3  **** 2 ****
2024/12/11 17:39:47 >>>      4  **** 3 ****
2024/12/11 17:39:48 >>>      5  **** 4 ****