我正在运行Windows的Docker桌面的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()
的调用所覆盖,但是在scanner.Scan()
完成之前不会再对write
进行调用,所以我不会认为这里没有比赛条件。
要检查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()))
}
}
这就是调用execute
和write
的方式。命令输出将作为服务器端事件发送到客户端。
execute(cmdInfo.cmd, func(data []byte) {
fmt.Fprintf(w, "data: %s\n\n", data)
flusher.Flush()
})
在* nix环境中运行容器时,似乎没有这个问题。问题可能出在Windows的Docker桌面上。