Docker 管道命令输出时的结果不一致

Docker 管道命令输出时的结果不一致,docker,go,debian,Docker,Go,Debian,我正在运行docker Desktop for Windows的Debian docker容器中执行一个命令(实际上是各种bash脚本),并获得如下输出: func execute(cmd *exec.Cmd, write func([]byte)) { cmdReader, err := cmd.StdoutPipe() if err != nil { write([]byte(fmt.Sprintf("error getting stdout pip

我正在运行docker Desktop for Windows的Debian docker容器中执行一个命令(实际上是各种bash脚本),并获得如下输出:

func execute(cmd *exec.Cmd, write func([]byte)) {
    cmdReader, err := cmd.StdoutPipe()
    if err != nil {
        write([]byte(fmt.Sprintf("error getting stdout pipe: %v", err)))
        return
    }
    cmd.Stderr = cmd.Stdout

    scanner := bufio.NewScanner(cmdReader)

    go func() {
        for scanner.Scan() {
            write(scanner.Bytes())
        }
    }()

    err = cmd.Start()
    if err != nil {
        write([]byte(err.Error()))
        return
    }

    err = cmd.Wait()
    if err != nil {
        write([]byte(err.Error()))
    }
}
对于其中一个更复杂的命令/脚本,扫描程序似乎在命令的输出实际完成之前完成,没有出现错误。在一些运行中,我得到了预期的全部输出,而在其他运行中,它缩短了输出

我连接到容器并多次手动执行命令/脚本,我总是得到预期的完整输出,这让我觉得这段代码有问题。我知道
scanner.Bytes()
返回下一次调用
scanner.Scan()
可能会覆盖的底层切片,但在
write
完成之前,不会再调用
scanner.Scan()
,所以我认为这里没有任何竞争条件

为了检查go程序中的扫描仪是否有问题,我试着这样做,但结果不一致。我错过了什么

func execute(cmd *exec.Cmd, write func([]byte)) {
    cmdReader, err := cmd.StdoutPipe()
    if err != nil {
        write([]byte(fmt.Sprintf("Error getting stdout pipe: %v", err)))
        return
    }
    cmd.Stderr = cmd.Stdout

    scanner := bufio.NewScanner(cmdReader)
    errCh := make(chan error)

    go func() {
        errCh <- cmd.Run()
    }()

    for scanner.Scan() {
        write(scanner.Bytes())
    }

    err = <-errCh
    if err != nil {
        write([]byte(err.Error()))
    }
}

在*nix环境中运行容器时,我似乎没有遇到这个问题。问题可能是Docker Desktop for Windows的问题。

写函数对并发调用安全吗?write函数是否保留对传递给它的切片的引用?数据丢失是因为没有任何东西等待扫描循环完成吗?@MuffinTop我编辑了这个问题,正在使用第二个版本的
execute
,扫描仪不在go例程中
Run()
应调用
cmd.Start()
cmd.Wait()
,完成后应关闭扫描仪。在*nix环境中运行容器时,我似乎没有此问题。问题可能与Docker Desktop for Windows有关。写入函数对于并发调用是否安全?write函数是否保留对传递给它的切片的引用?数据丢失是因为没有任何东西等待扫描循环完成吗?@MuffinTop我编辑了这个问题,正在使用第二个版本的
execute
,扫描仪不在go例程中
Run()
应调用
cmd.Start()
cmd.Wait()
,完成后应关闭扫描仪。在*nix环境中运行容器时,我似乎没有此问题。问题可能出在Docker Desktop for Windows上。
execute(cmdInfo.cmd, func(data []byte) {
    fmt.Fprintf(w, "data: %s\n\n", data)
    flusher.Flush()
})