Subprocess and stdio processing

Hello,

I am creating a server side program running on debian where I need to spwan a subprocess in a go routine.
This subprocess itself is a server that creates continuous output on its stdout.
I want to listen to this stdout and process the data and I want to monitor the process (if its running or not and stderr).
My main problem is how I can create a “listener” to the sdtout of the process that reads continuous output of single messages like that:
message, 60s pause, message, 1s pause, message, message, 10s pause, message …
At the moment I have this running with NodeJS, but i want to switch over to Go.

Thank you in advance.

Stefan

I am not sure if this is exactly what you want to do, but you probably just need the os/exec package. It allows you to run an external process and tap into its 3 Std pipes.
If you need to respond to each of these “messages” you probably need to create some logic around the Reader interface, but someone should be able to help you with that :smile:
Probably someone with more experience here can tell you more about the best practices around that package, I have only used it for “quck’n’dirty” solutions so far.

1 Like

If you are writing the subprocess as well as the master program, you might want to look into pie, it does exactly what you’re looking for: https://github.com/natefinch/pie

It assumes you’ll be able to handle RPC in the subprocess. If the subprocess isn’t under your control or can’t be rewritten to use RPC, you can still look at how pie handles reading stdout… the key is os/exec’s StdoutPipe: https://golang.org/pkg/os/exec/#Cmd.StdoutPipe

It gives you an io.Reader that is hooked up the the stdout of the process… you just read from that.

3 Likes

Thank you. The subprocess isnt under my control but i will look at it.

I found a fast solution that meets my basic requirements:

package main

import (
   "os/exec"
   "io"
   "fmt"
   "bufio"
)

func main(){
   myCmd :=  exec.Commad("command", "-arg")
   cmdOut, _ := myCmd.StdoutPipe()
   cmdErr, _ := myCmd.StderrPipe()

   go readPipe(cmdOut, "Output: ")
   go readPipe(cmdErr, "Error: ")
   myCmd.Start()

   var input string
   fmt.Scanln(&input)
}

func readPipe(reader io.Reader, prefix string){
   r := bufio.NewReader(reader)
   var outStr string
   var line []byte
   for true {
      line, _, _ = r.ReadLine()
      if line != nil {
         outStr = string(line)
         fmt.Println(prefix + outStr)
      }
   }   
}
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.