我正在尝试执行一个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] 删除。
我来说两句