0

I'm running a command in Go via exec.Command and scanning the output. On some systems the output is immediate. But on some systems the output seems to be buffered. Unless the amount of data produced by the command is large enough, I don't actually receive the output.

Is there anyway to get more immediate output, reliably?

package main

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

func main() {
        cmd := exec.Command("udevadm", "monitor")
        stdout, err := cmd.StdoutPipe()
        if err != nil {
                log.Fatal(err)
        }

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

        for {
                p := make([]byte, 10)
                n, _ := stdout.Read(p)
                fmt.Println("@ ", time.Now().Unix(), " ", n)
        }
}
Noah Watkins
  • 5,446
  • 3
  • 34
  • 47
  • 2
    You cannot. It's up to the program being executed whether it buffers its output or not. Most things use `glibc`, which fully buffers stdout by default. – JimB Apr 05 '19 at 20:25
  • Good point. However, when I run `udevadm` on the CLI the output is immediate as well. – Noah Watkins Apr 05 '19 at 20:28
  • 1
    the `glibc` stdout is fully buffered by default, but line buffered when writing to a tty. If you want to introduce the additional burden of creating a pty, then you can get the output faster. – JimB Apr 05 '19 at 20:30
  • 1
    Ahh, of course. Thanks. I suppose there must be a command that will run a target command in a ptty and pass stdout back through the pipe unbuffered? – Noah Watkins Apr 05 '19 at 20:33
  • 1
    Well, there's a series of syscalls you can use to create a pty to give to your program. Library recommendation are off-topic for answers here, but take a look at `github.com/kr/pty` for example – JimB Apr 05 '19 at 20:35
  • `stdbuf -oL ...` works ok – Noah Watkins Apr 05 '19 at 20:54
  • See related this [related question](https://stackoverflow.com/questions/3332045/bash-force-execd-process-to-have-unbuffered-stdout). – Charlie Tumahai Apr 06 '19 at 00:24

1 Answers1

0

I will propose that running stdbuf -oL udevadm <args> will achieve effectively what i"m after (line buffered output).

Noah Watkins
  • 5,446
  • 3
  • 34
  • 47