【问题标题】:Running command and get the output online运行命令并在线获取输出
【发布时间】:2018-02-18 08:00:31
【问题描述】:

我使用以下代码有效,问题是在进程完成执行时打印输出, 我想将输出实时打印到屏幕上,并且在进程完成时不提供所有输出,我该如何实现?

cmdParams := [][]string{
    {filepath.Join(dir,path), "npm", "install"},
    {filepath.Join(pdir,n.path), "gulp"},
}

for _, cp := range cmdParams {
    log.Printf("Starting %s in folder %s...", cp[1:], cp[0])
    cmd := exec.Command(cp[1], cp[2:]...)
    cmd.Dir = cp[0]
    // Wait to finish, get output:
    out, err := cmd.Output()
    if err != nil {
        log.Printf("Error running %s: %v\n", cp[1:], err)
        return
    }
    log.Println("Finished %s, output: %s", cp[1:], out)
}

更新在尝试提出的解决方案时,我得到了类似的输出

2018/02/18 11:11:57  Starting [npm install] in folder ...
2018/02/18 11:12:14 adde
2018/02/18 11:12:14 d 56
2018/02/18 11:12:14 3 pa
2018/02/18 11:12:14 ckag
2018/02/18 11:12:14 es i
2018/02/18 11:12:14 n 15
2018/02/18 11:12:14 .477
2018/02/18 11:12:14 s
2018/02/18 11:12:14 Finished %s [npm install]

【问题讨论】:

  • @icza - 所以我应该在这种情况下使用oneByte := make([]byte, 1) for { _, err := stdout.Read(oneByte) if err != nil { break } fmt.Printf("%c", oneByte[0]) } 吗?如果是的话在哪里?这有点令人困惑......
  • 使用建议副本的已接受答案中的解决方案。
  • @icza - 你是说 -scanner := bufio.NewScanner(stdout) scanner.Split(bufio.ScanRunes) 吗?
  • @icza - 如果你能提供我的上下文示例,那就太好了,因为我阅读了这篇文章并且它有所不同,我运行了几个命令,我使用了 cmd.Output(),我不明白如何把它们联系起来……

标签: go


【解决方案1】:

使用此答案中提出的解决方案:Streaming commands output progress

cmdParams := [][]string{
    {filepath.Join(dir, path), "npm", "install"},
    {filepath.Join(pdir, n.path), "gulp"},
}
for _, cp := range cmdParams {
    log.Printf("Starting %s in folder %s...", cp[1:], cp[0])
    cmd := exec.Command(cp[1], cp[2:]...)
    cmd.Dir = cp[0]

    stdout, err := cmd.StdoutPipe()
    if err != nil {
        log.Printf("%s cmd.StdoutPipe() error: %v\n", cp[1:], err)
        return
    }
    // Start command:
    if err = cmd.Start(); err != nil {
        log.Printf("%s start error: %v\n", cp[1:], err)
        return
    }

    // Stream command output:
    scanner := bufio.NewScanner(stdout)
    scanner.Split(bufio.ScanRunes)
    for scanner.Scan() {
        fmt.Print(scanner.Text())
    }
    if scanner.Err() != nil {
        log.Printf("Reading %s stdout error: %v\n", cp[1:], err)
        return
    }

    // Get execution success or failure:
    if err = cmd.Wait(); err != nil {
        log.Printf("Error running %s: %v\n", cp[1:], err)
        return
    }
    log.Printf("Finished %s", cp[1:])
}

一些解释:

这一行:

scanner := bufio.NewScanner(stdout)

创建一个bufio.Scanner,它将从提供进程写入的输出的管道中读取。

这一行:

scanner.Split(bufio.ScanRunes)

指示扫描器通过runes 读取输入,而不是默认的by-lines。

请注意,上面的示例仅流式传输进程的标准输出。如果你还需要它的标准错误流,你也可以从Command.StderrPipe()阅读。

另请注意,这不适用于某些不会将所有内容写入其标准输出或错误的命令。详情见How to get the realtime output for a shell command in golang?

【讨论】:

  • 谢谢 1+,你能看到我的更新为什么输出是这样的吗?
  • 我认为这是因为 count, err := stdout.Read(oneRune) ,知道如何克服这个问题吗?
  • 谢谢,我试过了,现在更糟了2018/02/18 11:44:14 a 2018/02/18 11:44:14 d 2018/02/18 11:44:14 d 2018/02/18 11:44:14 e 2018/02/18 11:44:14 d 2018/02/18 11:44:14 2018/02/18 11:44:14 5
  • 每个字节换行
  • @RaynD 在流式传输输出时请注意我使用fmt.Printf() log.Printf()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
  • 2010-10-13
相关资源
最近更新 更多