Docker 管道命令输出时的结果不一致
我正在运行docker Desktop for Windows的Debian docker容器中执行一个命令(实际上是各种bash脚本),并获得如下输出: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
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()
})