如何从一系列向stdout发出错误的exec命令中获取错误消息

时间:2016-11-18 18:13:34

标签: go pipe exec

在我的搜索中,我发现了很多关于如何检索单个exec命令的stdOut错误的例子,但我正在努力解决整个事物链。

在我的实际代码中,我有5个exec进程和一个由io管道连接的结果的文件写入。这是我正在进行的简化版本,在现实世界中,来自管道的stdOut被用作下一个进程的stdIn,直到我们复制到最终文件写入:

    fileOut, err := os.Create(filePath)
    if err != nil {
        return fmt.Errorf("file create error: %s : %s", filePath, err)
    }

    writer := bufio.NewWriter(fileOut)
    defer writer .Flush()

    var exSortStdErr bytes.Buffer

    sort := exec.Command("sort", sortFlag)
    sort.Stderr = &sortStdErr
    sortStdOut, err := sort.StdoutPipe()

    if err != nil {
        return fmt.Errorf("sort pipe error: %s : %s", err, sortStdErr.String())
    }

    if err := sort.Start(); err != nil {
        return fmt.Errorf("sort start error : %s : %s", err, sortStdErr.String())
    }

    io.Copy(writer, sortStdOut)

    if err = sort.Wait(); err != nil {
        //catching error here
        return fmt.Errorf("sort wait error : %s: %s", err, sortStdErr.String())
    }

我已经简化了上面的内容来说明这一点(因此实际的过程抛出错误并不存在),但我知道我得到的错误与链中的io管道连接的exec进程之一有关如上所述,但有问题的过程将其错误发送到stdOut,从我看到的终端重新创建

  

comm:文件1不按排序顺序

来自一个位于某处的comm进程,但我从最终的错误捕获中看到的只是:

  

退出状态1

我看到的例子建议从stdOut读取这样的东西:

var sortStdErr, sortStdOut bytes.Buffer
sort:= exec.Command("sort", sortFlag)
sort.Stdout = &sortStdOut
sort.Stderr = &sortStdErr

if err := sort.Run(); err !=nil {
    fmt.Println("error: %s %s", err, sortStdOut)
} 

这确实有效,但我不知道如何将结果与下一个过程相结合。有没有办法从cmd.wait错误处理中读取管道错误,还是有更好的方法?

在1.7上,虽然我怀疑这很重要。

如果有人可以指出我正确的方向,理想情况下有一个例子,那将非常感激。

1 个答案:

答案 0 :(得分:0)

试试这个:

var firstStdErr, firstStdOut bytes.Buffer
firstCommand := exec.Command(
    "sort",
    sortFlag,
)

firstCommand.Stdout = &firstStdOut
firstCommand.Stderr = &firstStdErr
if err := firstCommand.Run(); err !=nil {
    fmt.Println("error: %s %s %s", err, firstStdErr, firstStdOut)
} else{
    waitStatus := firstCommand.ProcessState.Sys().(syscall.WaitStatus)
    if waitStatus.ExitStatus() != 0 {
        fmt.Println("Non-zero exit code: " + strconv.Itoa(waitStatus.ExitStatus()))
    }
}
var secondStdErr, secondStdOut bytes.Buffer
secondCommand := exec.Command(
    "command 2",
)
secondCommand.Stdin = &firstStdOut
secondCommand.Stdout = &secondStdOut
secondCommand.Stderr = &secondStdErr
if err := secondCommand.Run(); err !=nil {
    fmt.Println("error: %s %s %s", err, secondStdErr, secondStdOut)
}
fileOut, err := os.Create(filePath)
if err != nil {
    fmt.Errorf("file create error: %s : %s", filePath, err)
}
defer fileOut.Close()

// sample writing to a file
fileOut.Write(firstStdErr.Bytes())
fileOut.Write(firstStdOut.Bytes())
fileOut.Write(secondStdOut.Bytes())