Golang io.Copy 内部 ReadFrom 中的块

iam*_*her 0 go

我正在 golang 中构建一个终端模拟器,我试图运行分离的进程,我可以从中复制输出并将其显示给用户,但是 io.Copy 功能块,因此我无法继续输出部分

我查看了源代码,它阻止了内部 ReadFrom 方法,我不明白为什么会这样

package main

import (
    "bytes"
    "fmt"
    "io"
    "os"
)

func main() {
    inputReader, inputWriter, _ := os.Pipe()
    outputReader, outputWriter, _ := os.Pipe()

    io.Copy(inputWriter, bytes.NewReader([]byte("\n")))

    stdin := inputReader
    stdout := outputWriter
    stderr := outputWriter

    var attr = os.ProcAttr{
        Dir: "/tmp",
        Env: nil,
        Files: []*os.File{
            stdin,
            stdout,
            stderr,
        },
        Sys: nil,
    }

    process, startProcessErr := os.StartProcess("/usr/bin/ls", []string{"ls"}, &attr)
    if startProcessErr != nil {
        panic(startProcessErr)
    }

    if releaseProcessErr := process.Release(); releaseProcessErr != nil {
        panic(releaseProcessErr)
    }

    var output bytes.Buffer
    io.Copy(&output, outputReader)
    fmt.Println(output)
}
Run Code Online (Sandbox Code Playgroud)

也许是因为我发布了流程,但我认为它不应该发生

Cer*_*món 5

调用io.Copy(&output, outputReader)阻塞,直到读取outputReader返回 EOF 或其他一些错误。Read onoutputReader不会返回 EOF,因为管道的写入端在父进程中仍处于打开状态。通过关闭父进程中的编写器来修复。

...

if releaseProcessErr := process.Release(); releaseProcessErr != nil {
    panic(releaseProcessErr)
}

outputWriter.Close() // <-- add this line

var output bytes.Buffer
io.Copy(&output, outputReader)
fmt.Println(output)

...
Run Code Online (Sandbox Code Playgroud)

使用os/exec包来简化代码:

cmd := exec.Command("/usr/bin/ls")
cmd.Dir = "/tmp"
output, err := cmd.CombinedOutput()
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(output))
Run Code Online (Sandbox Code Playgroud)