2017-07-04 28 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

相關問題