我知道os.Stdout
指向系统的标准输出,它实际上是一个文件指针
我的理解是,理论上os.Stdout
和os.File
应该是可互换的,并且它们都实现了io.Writer
接口
但我有以下代码
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("bash", "-c", "tail -f ~/test.log | grep h")
//f, _ := os.OpenFile("tt.log", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
//defer f.Close()
cmd.Stdout = os.Stdout
//cmd.Stdout = f
cmd.Start()
cmd.Wait()
}
type testWriter struct {}
func (t *testWriter) Write(p []byte) (n int, err error) {
fmt.Println(p)
return len(p), nil
}
当我将cmd.Stdout
指向os.Stdout
时,此代码运行良好,但当我将cmd.Stdout
指向文件指针时,它无法输出任何
我不明白为什么。有人能告诉我os.Stdout
为什么有效吗?为什么os.File
不工作?
我尝试过其他命令,如cat
、ls
,它们都能正常工作
我也尝试过自己实现io.Writer
,但我无法接收任何内容
我需要帮助,请帮帮我,谢谢
更新:
感谢@ElapsedSoul的建议。
我知道文件的输出中有一个缓冲区。我尝试在两种情况下刷新缓冲区,但都没有成功。代码如下
func main() {
cmd := exec.Command("bash", "-c", "tail -f ~/test.log | grep h")
//f, _ := os.OpenFile("tt.log", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
//defer f.Close()
cmd.Stdout = &testWriter{}
//cmd.Stdout = f
cmd.Start()
cmd.Wait()
}
type testWriter struct{}
func (t *testWriter) Write(p []byte) (n int, err error) {
os.Stdout.Write(p)
os.Stdout.Sync()
return len(p), nil
}
还有以下方式
func main() {
cmd := exec.Command("bash", "-c", "tail -f ~/test.log | grep h")
f, _ := os.OpenFile("tt.log", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
defer f.Close()
//cmd.Stdout = &testWriter{}
cmd.Stdout = f
go func() {
for {
f.Sync()
time.Sleep(1 * time.Second)
}
}()
cmd.Start()
cmd.Wait()
}
使用命令标志(--line buffered for grep(或stdbuf命令禁用输出缓冲。