通过gzip将命令输出到Reader

费尔明席尔瓦(Fermin Silva):

我正在尝试执行一个shell命令并压缩它的输出。问题是我然后需要与需要Reader的API进行接口。

为此,我尝试使用以下代码(简化代码):

package main

import (
    "encoding/hex"
    "testing"
    "fmt"
    "io"
    "io/ioutil"
    "os/exec"
    "compress/gzip"
)

func TestPipe(t *testing.T) {
    cmd := exec.Command("echo", "hello_from_echo")

    reader, writer := io.Pipe()
    gzW := gzip.NewWriter(writer)

    cmd.Stdout = gzW 
    cmd.Start()

    go func() {
        fmt.Println("Waiting")
        cmd.Wait()
        fmt.Println("wait done")
        // writer.Close()
        // gzW.Close()
    }()

    msg, _ := ioutil.ReadAll( reader )
    fmt.Println( hex.EncodeToString( msg ) )
}

问题是ReadAll永远挂起。如果我关闭,gzW一切都不会真正改变。但是,如果我关闭该writer变量,则程序立即完成而不会挂起,但是输出为:

$ go test -run Pipe
Waiting
wait done
1f8b080000096e8800ff
PASS

但是,无论我回显什么,输出都是一样的。如果我从这样的命令行尝试:echo "hello_from_echo" | gzip | hexdump输出完全不同,那么这种方法有问题。

任何线索可能是什么问题?

提前致谢

吉姆:

您以错误的顺序关闭了gzip编写器和管道编写器。您需要关闭gzip.Writer来刷新所有缓冲区并编写gzip页脚,然后可以关闭PipeWriter来取消阻止ReadAll同时添加WaitGroup确保您不会在任何关闭呼叫中被阻止的功能。

cmd := exec.Command("echo", "hello_from_echo and more")

pr, pw := io.Pipe()
gzW := gzip.NewWriter(pw)

cmd.Stdout = gzW
cmd.Start()

var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    err := cmd.Wait()
    if err != nil {
        log.Println(err)
    }
    gzW.Close()
    pw.Close()
}()

buf, err := ioutil.ReadAll(pr)
if err != nil {
    t.Fatal(err)
}
wg.Wait()
fmt.Println(hex.EncodeToString(buf))

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章