子命令实时Golang管道输出

Posted

技术标签:

【中文标题】子命令实时Golang管道输出【英文标题】:Golang pipe output of subcommand real time 【发布时间】:2015-06-18 19:29:45 【问题描述】:

我正在尝试通过管道输出命令的输出,但在关闭写入端之前似乎没有从管道中读取任何数据。最终,我希望它连接到一个 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 > %s\n", 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 秒,并且有源源不断的更新,所以一次全部通过很烦人。

【问题讨论】:

相关:Streaming commands output progress @icza 感谢您将我指向那里,但不幸的是它并没有太大帮助。那里的人与我的设置几乎相同。起初我认为问题在于它无法读取我文件中的换行符,但 scanner.Scan() 循环在输出的每一行执行一次,因此扫描分隔符应该可以正常工作 你试过把cmd.StdoutPipe连接到os.Stdout吗? 【参考方案1】:

原来问题不在我上面发布的代码中。这按预期工作。问题是正在执行的 C 程序没有正确刷新stdout。当以交互方式运行它时,它按预期工作,但是当stdout 被管道传输时,它实际上不会被写入,直到我调用flush。在c程序中手动添加一些flush语句后,go代码按预期运行。

【讨论】:

感谢您在弄清楚后回来写下这个答案!我为此失去了理智!我只有 python 脚本有类似的问题。【参考方案2】:

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

View other sample online@去游乐场

【讨论】:

以上是关于子命令实时Golang管道输出的主要内容,如果未能解决你的问题,请参考以下文章

golang 在golang中获取shell命令的实时输出

golang调用shell命令标准输出阻塞管道

golang父进程通过管道向子进程传递数据

golang [Golang]执行长时间运行的作业并流式传输实时输出

golang 将套接字附加到标准输入/标准输出

如何使用通道对 golang 管道阶段中的项目进行批处理?