下面的代码完全符合我的要求,只将其打印到控制台。
cmd := exec.Command("php", "randomcommand.php") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { log.Fatal(err) }
randomcommand.php:
// randomcommand.php simply alternates output between stdout and stderr 20 times $stdout = fopen('php://stdout', 'w+'); $stderr = fopen('php://stderr', 'w+'); for ($i = 1;$i <= 20; $i++) { fwrite($stdout, "stdout $i\n"); fwrite($stderr, "stderr $i\n"); }
输出:
stdout 1 stderr 1 stdout 2 stderr 2 stdout 3 stderr 3 stdout 4 stderr 4 stdout 5 stderr 5 stdout 6 stderr 6 stdout 7 stderr 7 stdout 8 stderr 8 stdout 9 stderr 9 stdout 10 stderr 10 stdout 11 stderr 11 stdout 12 stderr 12 stdout 13 stderr 13 stdout 14 stderr 14 stdout 15 stderr 15 stdout 16 stderr 16 stdout 17 stderr 17 stdout 18 stderr 18 stdout 19 stderr 19 stdout 20 stderr 20
我想要实现的是:
我试过将stdout和stderr命令传递到扫描仪中或使用io.Copy,它们分别在goroutine中进行,但是未维护输出顺序。可能是因为goroutine之间的交替必须在输出交替的同时发生,这几乎是不可能的。
我也尝试过使用“中选择”作为从例子在这里。但是没有保持输出顺序。
Logstreamer也存在同样的问题。
我必须尝试的另一个想法是看看是否可以从控制台缓冲区中读取内容,但这感觉不对。
有谁知道这是否有可能并且值得追求?
正如我在评论部分中所述,可以使用MultiWriter来实现
package main import ( "io" "log" "os" "os/exec" ) func main() { // Logging capability f, err := os.OpenFile("log.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { log.Fatalf("Error opening file: %v", err) } defer f.Close() mwriter := io.MultiWriter(f, os.Stdout) cmd := exec.Command("ls") cmd.Stderr = mwriter cmd.Stdout = mwriter err = cmd.Run() //blocks until sub process is complete if err != nil { panic(err) } }
在声明命令时以及在运行命令之前,只需指定Stdout和Stderr使用上面定义的MultiWriter。该MultiWriter实例包含一个日志文件和标准输出。