处理完成后读取stderr

I call imagemagick's convert command with some data I have in memory (from html form upload/web server). This works fine, but I'd like to get the error output of convert in case of an error. How can I do that?

This is my code:

package main

import (
    "bytes"
    "io"
    "io/ioutil"
    "log"
    "os/exec"
    "path/filepath"
)

func runImagemagick(data []byte, destfilename string) error {
    data_buf := bytes.NewBuffer(data)

    cmd := exec.Command("convert", "-", destfilename)
    stdin, err := cmd.StdinPipe()
    if err != nil {
        return err
    }

    err = cmd.Start()
    if err != nil {
        return err
    }
    _, err = io.Copy(stdin, data_buf)
    if err != nil {
        return err
    }
    stdin.Close()
    err = cmd.Wait()
    if err != nil {
        return err
    }
    return nil
}

func main() {
    data, err := ioutil.ReadFile("source.gif")
    if err != nil {
        log.Fatal(err)
    }
    err = runImagemagick(data, filepath.Join("/tmp", "abc", "dest.png"))
    if err != nil {
        log.Fatal(err)
    }
}

Now the artificial problem is that the directory /tmp/abc/ does not exist. Normally convert would give me this result:

$ convert - /tmp/abc/foo.png < source.gif 
convert: unable to open image `/tmp/abc/foo.png': No such file or directory @ error/blob.c/OpenBlob/2617.
convert: WriteBlob Failed `/tmp/abc/foo.png' @ error/png.c/MagickPNGErrorHandler/1755.

but I don't "see" this error message within my small program. How can I get the error message and show it to my user?

(And another sub-question is: can you give me an advice if this code looks OK? Are there any obvious flaws in it?)

Pipe stdout and stderr too. For example,

package main

import (
    "bytes"
    "io"
    "io/ioutil"
    "log"
    "os/exec"
    "path/filepath"
)

func runImagemagick(data []byte, destfilename string) error {
    cmd := exec.Command("convert", "-", destfilename)
    stdin, err := cmd.StdinPipe()
    if err != nil {
        return err
    }
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        return err
    }
    stderr, err := cmd.StderrPipe()
    if err != nil {
        return err
    }
    err = cmd.Start()
    if err != nil {
        return err
    }
    _, err = io.Copy(stdin, bytes.NewBuffer(data))
    if err != nil {
        return err
    }
    stdin.Close()
    outData, err := ioutil.ReadAll(stdout)
    if err != nil {
        return err
    }
    if len(outData) > 0 {
        log.Print(string(outData))
    }
    errData, err := ioutil.ReadAll(stderr)
    if err != nil {
        return err
    }
    if len(errData) > 0 {
        log.Print(string(errData))
    }
    err = cmd.Wait()
    if err != nil {
        return err
    }
    return nil
}

func main() {
    data, err := ioutil.ReadFile("source.gif")
    if err != nil {
        log.Fatal(err)
    }
    err = runImagemagick(data, filepath.Join("/tmp", "abc", "dest.png"))
    if err != nil {
        log.Fatal(err)
    }
}

Output:

2013/03/03 15:02:20 convert.im6: unable to open image `/tmp/abc/dest-0.png': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: WriteBlob Failed `/tmp/abc/dest-0.png' @ error/png.c/MagickPNGErrorHandler/1728.
2013/03/03 15:02:20 exit status 1
exit status 1

There's no need to use pipes because bytes.Buffer implements the io.Writer interface and so it can be used just fine to collect the program's output:

func runImagemagick(data []byte, destfilename string) error {     
    cmd := exec.Command("convert", "-", destfilename)

    var stdout, stderr bytes.Buffer
    cmd.Stdout = &stdout
    cmd.Stderr = &stderr

    err := cmd.Run()
    if err != nil {
        if ee, ok := err.(*exec.ExitError); ok {
            return &imagemagickError{ee, stdout.Bytes(), stderr.Bytes()}
        } else {
            return err
        }
    }

    if stderr.Len() > 0 {
        return errors.New(fmt.Sprintf("imagemagick wrote to stderr: %s", stderr.Bytes()))
    }

    if stdout.Len() > 0 {
        log.Print(stdout.Bytes())
    }
    return nil
 }