我正在远程计算机上通过SSH执行一堆操作,并且正在流式传输其stdout和stderr,然后由写入器将其使用,写入器将其与字节缓冲区一起写入本地stdout和stderr。 / p>
就在作者使用它之前,我想对其进行一系列字符串操作,然后将其写入屏幕和缓冲区。到此为止,一切都正常且花哨。
我的问题是现在它不再是流,它会挂起,然后将整个glob分成一个块输出。我希望它是实时的,因此我将频道添加到我的执行例程中,但没有任何改善。以下是我的功能,请告诉我您是否可以找到原因,或者可能是实现此目的的更好方法。
//发送
func handleStdStream(filters []string, replaceFilters map[string]string, pipe io.Reader, readers chan io.Reader) {
if filters != nil {
// filters exist
// read first 8 bytes
res := readPipe(8, pipe)
// get each line from the resulting streamed output
for _, str := range strings.Split(res, "\n") {
if str != "" {
out := lineFilterAndReplace(str, filters, replaceFilters)
// instantiate an io.Reader obj from the given string
outReader := strings.NewReader(out)
readers <- outReader
}
}
} else {
// filters dont exist
if len(replaceFilters) > 0 {
res := readPipe(8, pipe)
for _, str := range strings.Split(res, "\n") {
if str != "" {
out := lineReplace(str, replaceFilters)
// instantiate an io.Reader obj from the given string
outReader := strings.NewReader(out)
readers <- outReader
}
}
} else {
readers <- pipe
}
}
}
//正在接收
outReaders := make(chan io.Reader)
go handleStdStream(outFilters, replaceFilters, stdoutIn, outReaders)
go func() {
for {
pipe := <-outReaders
_, errStdout = io.Copy(outWriter, pipe)
}
// _, errStdout = io.Copy(outWriter, stdoutIn)
}()
答案 0 :(得分:1)
我认为您不需要渠道或goroutine来完成此任务。 Writer
和Reader
接口已经在流化;您连续从Reader
读取字节,直到遇到EOF或错误,然后连续将字节交给Writer
直到完成或出现错误。就其本身而言,处理流不需要任何并发性,因此在单个goroutine中按顺序执行此操作非常合适。
您不应忽略错误返回。如果函数或方法返回错误值,则需要检查它。对于I / O,通常会在返回错误时停止从Reader
读取,而在返回错误时通常需要停止向Writer
写入。对于Reader
,还必须检查特殊的“错误”值io.EOF
。
我认为使用Scanner
包中的bufio
比尝试自己进行缓冲/拆分要好。默认情况下,Scanner
在换行符上分割输入(Unix样式的LF或DOS样式的CRLF)。如果您仅通过io.EOF
与Reader
进行交互,那么它也无需检查Scanner
。
请考虑以下handleStdStream
版本:
func handleStdStream(filters []string, replaceFilters map[string]string, pipe io.Reader, w io.Writer) error {
scanner := bufio.NewScanner(pipe)
for scanner.Scan() {
str := scanner.Text()
if str == "" {
continue
}
out := ""
if len(filters) != 0 {
out = lineFilterAndReplace(str, filters, replaceFilters)
} else {
out = lineReplace(str, replaceFilters)
}
if _, err := w.Write([]byte(out)); err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
您将像这样使用它:
err := handleStdStream(filters, replaceFilters, pipe, outWriter)
if err != nil {
// do something, like printing the error to a log or stderr
}