【问题标题】:Pipe out both stdin and stdout os.exec Golang输出标准输入和标准输出 os.exec Golang
【发布时间】:2021-10-20 17:56:40
【问题描述】:

我正在尝试在 golang 中运行一个命令,将阅读器提供给它的标准输入,返回它的标准输出,然后将它的标准错误转换为错误消息。

我的问题是:我的代码只在管道输入标准输入并返回标准输出时工作得很好。但是,当我也尝试将 stderr 加载到缓冲区中时,如果 stdout 的信息多于 stdin,则该命令将挂起。我已经对此进行了测试,如果标准输出比标准输入大一个字节,它甚至适用。我已经坚持了几个小时,无法在互联网上找到任何解决方案。

以下是相关代码:

var b bytes.Buffer

cmd := exec.Command(convCmd, convArgs...)

stdin, _  := cmd.StdinPipe()
stdout, _ := cmd.StdoutPipe()
cmd.Stderr = &b

go func() {
    defer stdin.Close()
    io.Copy(stdin, inStream)
}()

err = cmd.Start()

if b.String == "" {
    err = nil
} else {
    err = errors.New(b.String()
}

return stdout, err

这个问题让我发疯了,我唯一的猜测是该命令正在等待 stdin 等于 stdout 的大小,但它似乎很奇怪,只有当我尝试将 stderr 加载到缓冲区时它才会这样做。

【问题讨论】:

  • 我试过 cmd.Wait(),它会导致命令总是挂起。
  • 顺便说一句,有问题的命令是 ImageMagick 的转换。 Inkscape 也失败了,但由于某种原因,它可以与 rsvg-convert 一起正常工作。
  • 你肯定需要Wait() 让它在这样启动时工作。该程序可能会挂起,因为它在没有更多数据时等待来自标准输入的更多数据。如果 - 而不是启动 goroutine - 你设置cmd.Stdin = inStream 然后使用cmd.Run()(或cmd.Wait()Start() 之后)会发生什么?也尽量不要忽略错误
  • 经过更多研究后,我发现了这个问题。结果 cmd.Wait() 一直等到 stdin 和 stdout 都完成写入,所以我试图将命令的 stdout 直接通过管道传递到函数的 return 是搞砸了。我的解决方案是从 cmd.Output() 创建一个新的阅读器,然后将其用作返回 io.Reader。经过一些测试,它似乎没有任何性能影响,我觉得有点奇怪。非常感谢您的帮助,我一定会在我的代码中添加适当的错误处理

标签: go stdout stdin stderr


【解决方案1】:

我确信这个问题还有其他几种解决方案,但我发现这个问题与将命令的标准输出直接传递到函数的返回有关。

    var b bytes.Buffer

    cmd := exec.Command(convCmd, convArgs...)
    stdin, err  := cmd.StdinPipe()
    if err != nil {
        return nil, err
    }

    cmd.Stderr = &b

    go func() {
        defer stdin.Close()
        io.Copy(stdin, n)
    }()

    // Run the command and buffer the output
    byteSlice, err := cmd.Output()
    stdout := bytes.NewReader(byteSlice)

    // If the command exits non-zero status, return stderr as the error message
    if err != nil {
        err = errors.New(b.String())
    }

    return stdout, err

我没有直接使用阅读器,而是使用了 cmd.Output() 来创建一个新的阅读器,现在命令有时间完成了。

【讨论】:

    猜你喜欢
    • 2013-09-18
    • 2013-06-13
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多