use*_*900 4 io synchronization go
下面的代码完全符合我的要求,除了它只打印到控制台.
cmd := exec.Command("php", "randomcommand.php")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
Run Code Online (Sandbox Code Playgroud)
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");
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
我想要实现的是:
我已经尝试将命令stdout和stderr连接到扫描仪或使用io.Copy,每个都在goroutine中,但是输出的顺序没有被维护.可能因为goroutines之间的交替必须在输出交替的同时发生,这几乎是不可能的.
我也尝试过使用"select",就像这里的例子一样.但是没有保持产出的顺序.
Logstreamer也有同样的问题.
我必须尝试的另一个想法是看看我是否能以某种方式从控制台缓冲区中读取,但这感觉不对.
有谁知道这是否可能,值得追求?
Dep*_*ado 12
正如我在评论部分所说,这可以使用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)
}
}
Run Code Online (Sandbox Code Playgroud)
声明命令时,在运行命令之前,只需指定Stdout和Stderr正在使用上面定义的MultiWriter.此MultiWriter实例包含日志文件和标准输出.