代理exec.Cmd Stdout / Stderr而不会丢失TTY

时间:2017-07-04 01:40:56

标签: go colors stdout stderr tty

我有以下代码执行任意shell命令并将stdoutstderr传送到终端。:

c := exec.Command("/bin/sh", "-c", cmd)
c.Stdin = os.Stdin
c.Stdout = os.Stdout
c.Stderr = os.Stderr

但是,我需要在打印之前处理输出,所以我用代理io.Writer接口包装它:

type ProxyWriter struct {
    file   *os.File
}

func NewProxyWriter(file *os.File) *ProxyWriter {
    return &ProxyWriter{
        file: file,
    }
}

func (w *ProxyWriter) Write(p []byte) (int, error) {
    // ... do something with bytes first
    fmt.Fprintf(w.file, "%s", string(p))
    return len(p), nil
}

所以原始代码现在是:

c := exec.Command("/bin/sh", "-c", cmd)
c.Stdin = os.Stdin
c.Stdout = NewProxyWriter(os.Stdout)
c.Stderr = NewProxyWriter(os.Stderr)

这大部分都有效,但stdoutstderr似乎不再符合TTY资格。任何以前的样式或彩色输出都不再有样式或颜色。

我已经确认这不是我的ProxyWriter的问题,只是通过将命令设置为以下内容来简化格式化,这会正确输出彩色文本。

c := exec.Command("echo", "\033[0;31mTEST\033[0m")

更明确的测试是:

c := exec.Command("/bin/sh", "-c", "if [ -t 1 ] ; then echo \"terminal\"; else echo \"not a terminal\"; fi")

哪个输出:

not a terminal

无论如何我可以在不丢失TTY状态的情况下包装命令stdout / stderr吗?

1 个答案:

答案 0 :(得分:0)

替换

func (w *ProxyWriter) Write(p []byte) (int, error) {
    // ... do something with bytes first
    fmt.Fprintf(w.file, "%s", string(p))
    return len(p), nil
}

func (w *ProxyWriter) Write(p []byte) (int, error) {
    return w.Write(p)
}

fmt.Fprintf有一些逻辑可以避免终端破坏。

相关问题