3

メモリにあるデータを使用してimagemagick のconvertコマンドを呼び出します (html フォームのアップロード/Web サーバーから)。これはうまくいきますが、エラーが発生した場合のエラー出力を取得したいと思いconvertます。どうやってやるの?

これは私のコードです:

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)
    }
}

ここでの人為的な問題は、ディレクトリ/tmp/abc/が存在しないことです。通常convert、次の結果が得られます。

$ 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.

しかし、私の小さなプログラムではこのエラー メッセージが「表示」されません。エラー メッセージを取得してユーザーに表示するにはどうすればよいですか?

(そして、別のサブ質問: このコードが問題ないように見える場合、アドバイスをいただけますか? 明らかな欠陥はありますか?)

4

2 に答える 2

1

パイプstdoutstderr。例えば、

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)
    }
}

出力:

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
于 2013-03-03T20:04:35.203 に答える
1

bytes.Bufferインターフェイスを実装しているため、パイプを使用する必要はありませんio.Writer。プログラムの出力を収集するために使用できます。

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
 }
于 2013-03-03T21:08:26.643 に答える