我正在编写一个测试函数,用于测试go程序与命令行程序的交互。那是
os.Stdio -> cmd.Stdin
cmd.Stdin -> os.Stdin
我可以用管道连接这些io,但是我会有一条传递管道的数据日志。我尝试使用io.MultiWriter,但它不是os.file对象,不能分配给os.Stdout。我发现了一些使用大量管道和io.copy的样品。但由于io.copy不具有交互性。如何用管道将Stdout连接到io.MultiWriter?
logfile, err := os.Create("stdout.log")
r, w, _ := os.Pipe()
mw := io.MultiWriter(os.Stdout, logfile, w)
cmd.Stdin = r
os.Stdout = mw // <- error in this line
错误消息,如
cannot use mw (variable of type io.Writer) as type *os.File in assignment:
发布于 2022-04-10 12:16:00
作为另一种解决方案,您可以使用单独的func来模拟MultiWriter,以读取已写入stdout
的内容,捕获它,然后将其写入文件和原始stdout
。
package main
import (
"bufio"
"fmt"
"os"
"time"
)
func main() {
originalStdout := os.Stdout //Backup of the original stdout
r, w, _ := os.Pipe()
os.Stdout = w
//Use a separate goroutine for non-blocking
go func() {
f, _ := os.Create("stdout.log")
defer f.Close()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
s := scanner.Text() + "\r\n"
f.WriteString(s)
originalStdout.WriteString(s)
}
}()
//Test
c := time.NewTicker(time.Second)
for {
select {
case <-c.C:
fmt.Println(time.Now())
fmt.Fprintln(os.Stderr, "This is on Stderr")
}
}
}
发布于 2022-04-11 04:59:31
我用管道、TeeReader和MultiWriter完成了一项工作。安装是一个测试函数,它通过stdin和stdout测试go程序与python程序的交互。
main.stdout -> pipe -> TeeReader-> (client.stdin,MultiWriter(log,stdout))
client.stdout -> MultiWriter(管道-> main.stdin,logfile,stdout )
稍后我将尝试添加更多的解释。
func Test_Interactive(t *testing.T) {
var tests = []struct {
file string
}{
{"Test_Client.py"},
}
for tc, tt := range tests {
fmt.Println("---------------------------------")
fmt.Printf("Test %d, Test Client:%v\n", tc+1, tt.file)
fmt.Println("---------------------------------")
// Define external program
client := exec.Command("python3", tt.file)
// Define log file
logfile, err := os.Create(tt.file + ".log")
if err != nil {
panic(err)
}
defer logfile.Close()
out := os.Stdout
defer func() { os.Stdout = out }() // Restore original Stdout
in := os.Stdin
defer func() { os.Stdin = in }() // Restore original Stdin
// Create pipe connect os.Stdout to client.Stdin
gr, gw, _ := os.Pipe()
// Connect os.Stdout to writer side of pipe
os.Stdout = gw
// Create MultiWriter to write to logfile and os.Stdout at the same time
gmw := io.MultiWriter(out, logfile)
// Create a tee reader read from reader side of the pipe and flow to the MultiWriter
// Repleace the cmd.Stdin with TeeReader
client.Stdin = io.TeeReader(gr, gmw)
// Create a pipe to connect client.Stdout to os.Stdin
cr, cw, _ := os.Pipe()
// Create MultWriter to client stdout
cmw := io.MultiWriter(cw, logfile, out)
client.Stdout = cmw
// Connect os stdin to another end of the pipe
os.Stdin = cr
// Start Client
client.Start()
// Start main
main()
// Check Testing program error
if err := client.Process.Release(); err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
log.Printf("Exit Status: %d", status.ExitStatus())
t.Errorf("Tester return error\n")
}
} else {
log.Fatalf("cmd.Wait: %v", err)
t.Errorf("Tester return error\n")
}
}
}
}
https://stackoverflow.com/questions/71811175
复制相似问题