2017-07-04 31 views
1

我已经得到下面的代码执行的任意的外壳命令和管道的stdoutstderr到终端。:代理exec.Cmd标准输出/标准错误,而不会失去TTY

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状态?

回答

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

+0

我假设你的意思是'w.file.Write'而不是'w.Write'?不幸的是,输出与'fmt.Fprintf'相同。 – kbirk

+0

你试过了吗?你是什​​么意思'限定TTY'?出现破坏的转义序列? – mattn

+0

是的,我尝试使用'返回w.file.Write(p)'。我认为'符合TTY'的意思是,如果我将os.Stdout包装在一个io.Writer接口中,并将'Cmd.Stdout'设置为它,它将*不符合终端。 – kbirk

相关问题