我正在尝试通过管道传输命令的输出,但在写入结束之前似乎没有从管道读取数据。最终,我希望它连接到一个 websocket,该 websocket 在执行命令时流式传输命令的状态。问题是,虽然此代码逐行打印消息,但在程序完成执行之前不会打印任何内容。
cmd := exec.Command(MY_SCRIPT_LOCATION, args)
// create a pipe for the output of the script
// TODO pipe stderr too
cmdReader, err := cmd.StdoutPipe()
if err != nil {
fmt.Fprintln(os.Stderr, "Error creating StdoutPipe for Cmd", err)
return
}
scanner := bufio.NewScanner(cmdReader)
go func() {
for scanner.Scan() {
fmt.Printf("t > %sn", scanner.Text())
}
}()
err = cmd.Start()
if err != nil {
fmt.Fprintln(os.Stderr, "Error starting Cmd", err)
return
}
err = cmd.Wait()
if err != nil {
fmt.Fprintln(os.Stderr, "Error waiting for Cmd", err)
return
}
有什么方法可以做类似的事情,让扫描仪在写入管道而不是写入所有内容后逐行读取?该程序运行大约需要 20 秒,并且有源源不断的更新,因此一次将它们全部完成很烦人。
事实证明,问题不在我上面发布的代码中。这按预期工作。问题是正在执行的 C 程序未正确刷新stdout
。以交互方式运行它时,它按预期工作,但是当stdout
被管道传输时,直到我调用flush
它才真正被写入。在手动将一些 flush 语句添加到 c 程序后,go 代码按预期工作。
F.Y.I
在写入管道时逐行阅读,而不是在写入所有内容后?
我发现该软件包对于那些通过谷歌搜索来讨论这个话题的人来说go-pipeline
非常有用。
- github.com/mattn/go-pipeline @ GitHub
以下相当于git log --online | grep first import | wc -l
package sample
import (
"fmt"
"log"
"github.com/mattn/go-pipeline"
)
func ExampleCommandPipeLine() {
out, err := pipeline.Output(
[]string{"git", "log", "--oneline"},
[]string{"grep", "first import"},
[]string{"wc", "-l"},
)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(out))
// Output:
// 1
}
- 在线查看其他示例@Go Playground