我有以下代码执行任意 shell 命令并将 stdout
和 stderr
通过管道传输到终端。
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)
这在大多数情况下都有效,但是,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?
最佳答案
替换
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/