我有以下代码执行任意shell命令并将stdout
和stderr
传送到终端。:
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)
这大部分都有效,但stdout
和stderr
似乎不再符合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吗?
答案 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
有一些逻辑可以避免终端破坏。