go - 代理 exec.Cmd Stdout/Stderr 不丢失 TTY

标签 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 接口(interface)包装了它:

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?

最佳答案

替换

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 有一些逻辑可以避免终端中断。

关于go - 代理 exec.Cmd Stdout/Stderr 不丢失 TTY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44895757/

相关文章:

go - 如何在 Golang 中将 []string 转换为 []float64?

objective-c - 快速将 UIColor 转换为 CGColor

javascript - 更改当前选定字段的颜色

python - reportlabs-python 中的颜色代码

c - 标准缓冲区在系统()调用之前没有被清除

使用 preg_match 去路由

go - 可执行文件 ("main"包中的公共(public)名称)

go - 无法使用 Go 在函数中覆盖列表类型接口(interface) {}

java - 从 java 到 python 的一个标准输出到一个标准输入

C 段错误源于读取标准输入然后操作该数据