10

The following works and prints the command output:

out, err := exec.Command("ps", "cax").Output()

but this one fails (with exit status 1):

out, err := exec.Command("ps", "cax | grep myapp").Output()

Any suggestions?

tgogos
  • 23,218
  • 20
  • 96
  • 128

3 Answers3

27

Passing everything to bash works, but here's a more idiomatic way of doing it.

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    grep := exec.Command("grep", "redis")
    ps := exec.Command("ps", "cax")

    // Get ps's stdout and attach it to grep's stdin.
    pipe, _ := ps.StdoutPipe()
    defer pipe.Close()

    grep.Stdin = pipe

    // Run ps first.
    ps.Start()

    // Run and get the output of grep.
    res, _ := grep.Output()

    fmt.Println(string(res))
}
Nadh
  • 6,987
  • 2
  • 21
  • 21
18

You could do:

out, err := exec.Command("bash", "-c", "ps cax | grep myapp").Output()
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • 1
    You won't be informed about the inner command errors when you use `bash -c`. The method that @Nadh suggests has the advantage that if the inner command i.e. `ps cax` fails and returns non zero value, an error will be returned. – therealak12 Mar 07 '22 at 13:45
2

In this specific case, you don't really need a pipe, a Go can grep as well:

package main

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

func main() {
   c, b := exec.Command("go", "env"), new(bytes.Buffer)
   c.Stdout = b
   c.Run()
   s := bufio.NewScanner(b)
   for s.Scan() {
      if strings.Contains(s.Text(), "CACHE") {
         println(s.Text())
      }
   }
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Zombo
  • 1
  • 62
  • 391
  • 407