0

When using exec.Command to run another command that outputs color, e.g.

func main() {
    c := exec.Command("node-gyp", "rebuild")
    c.Stdin = os.Stdin
    c.Stdout = os.Stdout
    c.Stderr = os.Stderr
    c.Run()
}

this works as expected and outputs colored text to the terminal, e.g:

colored terminal

However, consider if we wanted to to also capture the output stream for later use. We could do something like this (the colored output is on stderr):

func main() {
    c := exec.Command("node-gyp", "rebuild")
    c.Stdin = os.Stdin
    c.Stdout = os.Stdout
    var buf bytes.Buffer
    c.Stderr = io.MultiWriter(os.Stderr, &buf)
    c.Run()
    // do something with buf
}

Now, everything is in black and white:

monochrome output

This prompts two questions:

  • What's going on here? How can the simple act of essentially doing a tee on a Writer stream cause the terminal colors (which I'm guessing are UTF-8 symbols) to disappear?
  • If you use exec.Command("ls", "--color") instead, colors show up in both instances. Why do the colors work here and not for node-gyp rebuild? If they're encoded differently, what's the difference?
Andrew Mao
  • 35,740
  • 23
  • 143
  • 224
  • 2
    See [GoLang os/exec StdoutPipe with colors](https://stackoverflow.com/questions/45117214/golang-os-exec-stdoutpipe-with-colors) and [Preserve color codes when exec-ing](https://stackoverflow.com/questions/29375241/preserve-color-codes-when-exec-ing) – Charlie Tumahai Apr 09 '20 at 02:57
  • @CeriseLimón how would the program be able to tell, though, if it's piping to a go executable that's just writing to stdout versus writing to an `io.MultiWriter`? – Andrew Mao Apr 09 '20 at 16:05
  • 1
    In the first program, the parent program's stderr file descriptor is used as the child process stderr. The child process writes directly to the file descriptor. The child process output is not piped through the parent process. In the second program, the os/exec package creates an OS pipe and uses the write end of the pipe as the child process stderr. The os/exec package runs a goroutine to pump data from the read end of the pipe to the multiwriter. – Charlie Tumahai Apr 09 '20 at 16:23

0 Answers0