rexposadas
rexposadas

Reputation: 3189

How to process stderr in go?

I have an app called "myapp". That app simply writes to stderr.

The important bit is, I want to capture what is written in stderr and process it in real-time. How would I go about doing that?

I tried the code below. :

cmd := exec.Command("myapp") // this app prints lines to stderr
stderr, err := cmd.StderrPipe()
if err != nil {
    log.Fatal(err)
}

if err := cmd.Start(); err != nil {
    log.Fatal(err)
}

if b, err := ioutil.ReadAll(stderr); err == nil {
    log.Println(string(b))
}                                                                                                       

if err := cmd.Wait(); err != nil {
    log.Fatal(err)
}   

The code doesn't print out anyting. I suspect it's because ioutil.ReadAll() is not the proper func to call since it waits for EOF. How else would I read from the stderr pipe?

You can replace the command executed with anything that outputs to stdout or stderr like tail -f mylogfile. The point is, I want to process the lines as they are written to stdout.

Upvotes: 1

Views: 1557

Answers (2)

Ilia Choly
Ilia Choly

Reputation: 18557

Create a type that implements io.Writer and set that as the command's stderr writer.

type Processor struct{}

func (Processor) Write(b []byte) (int, error) {
    // intercept data here
    return os.Stdout.Write(b)
}

func main() {
    cmd := exec.Command("mycommand")
    cmd.Stderr = Processor{}
    _ = cmd.Run()
}

Upvotes: 1

cnicutar
cnicutar

Reputation: 182639

StderrPipe returns a ReadCloser. You can use that to create a bufio.Scanner and then read lines one by one:

sc := bufio.NewScanner(stderr)
for sc.Scan() {
    fmt.Printf("Line: %s\n", sc.Text());
}

Upvotes: 4

Related Questions