我正在从Go程序中执行docker-compose可执行文件。要配置它,我将docker-compose配置直接通过管道传递到docker-compose的stdin。在大多数情况下,这都可以正常工作,代码大致如下所示(为简单起见,我删除了代码段中的所有错误处理):
args = append([]string{"-f", "-"}, args...)
cmd := exec.Command("docker-compose", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = strings.NewReader(input)
cmd.Run()
args
是传递给docker-compose的参数,input
是作为YAML字符串的docker-compose配置。尽管这在大多数情况下都有效,但对于交互式命令而言却失败了。 Stdin未连接到os.stdin,命令失败。我可以使用以下代码获取交互式命令:
cmd := exec.Command("docker-compose", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Run()
但这并没有传递配置的内容,最后我需要这样做。我试图以某种方式组合这些版本,但无法正常工作:
input, _ := getDockerComposeAsYaml(config)
args = append([]string{"-f", "-"}, args...)
cmd := exec.Command("docker-compose", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
stdin, _ := cmd.StdinPipe()
go func() {
//defer stdin.Close()
io.WriteString(stdin, input)
}()
cmd.Run()
我尝试了上面的代码,无论是否显式关闭stdin,但所需的行为应该是不关闭stdin,因为我想保持stdin打开以进行交互使用。如果不关闭程序,则该程序将永远挂起,而关闭stdin则无法按预期进行交互。
将已执行程序的stdin连接到os.stdin,同时仍然能够在开始时通过管道传输一些正确的方法是什么?
最佳答案
写入stdin
(使用cmd.StdinPipe
创建的管道)的goroutine应该:
input
字符串os.Stdin
,将获取的所有内容写入stdin
os.Stdin
上遇到EOF时,请明确关闭stdin
。 但是,子进程可能在
os.Stdin
关闭之前退出。在这种情况下,管道(stdin
将由exec.Command
关闭)。您的循环应检查是否有闭合的stdin
,如果发生则退出goroutine。
关于go - 使用以编程方式编写并连接到os.stdin的stdin执行命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61247109/